How Do I Authenticate a User With Shiro? - shiro

I've gone over and over on how to have a user login with Shiro, but it still seems like a vital piece is missing: How does shiro authenticate a given username and password against stored usernames and passwords? The most I've figured out is It is each Realm's responsibility to match submitted credentials with those stored in the Realm's backing data store from here. But how is that done?
Below is what I've tried, but the result is still an invalid authentication.
LoginController
#RequestMapping(value = "/login.htm", method = RequestMethod.POST)
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object cmd, BindException errors) throws Exception {
LoginCommand command = (LoginCommand) cmd;
UsernamePasswordToken token = new UsernamePasswordToken(command.getUsername(), command.getPassword());
System.out.println("onSubmit");
System.out.println(token.getUsername());
System.out.println(token.getPassword());
try
{
SecurityUtils.getSubject().login(token);
} catch (AuthenticationException e) {
errors.reject("error.invalidLogin", "The username or password was not correct.");
}
if (errors.hasErrors()) {
return showForm(request, response, errors);
} else {
return new ModelAndView("accessTest");
}
}
Realm
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
System.out.println("doGetAuthenticationInfo");
System.out.println(user.getUsername());
System.out.println(user.getPassword());
// user is a test object in place of a database
if( user != null ) {
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
} else {
return null;
}
}

Discovered the answer. It was a foolish one. I copied some example code, and they set the credentials matcher to HashedCredentialsMatcher. I wasn't doing any hashing, so it didn't work. Removed the setCredentialsMatcher and it worked.

Related

Spring Security OAuth2 How to generate temporary token for file download

In my app I'm using Spring Security Authorization server and Spring Security Resource server. Everything works fine, user logs in, gets issued access_token and can use it to access the API.
Now I need to allow the user to download a file from URL (think <button onClick="window.open(/files/1/download")>.
My idea is to create new endpoint which will issue a temporary access_token to the user and the user then can add it as part of URL windows.open('/files/1/download?access_token=<temp-token>')
I have tried using TokenEndpoint and AuthorizationServerTokenServices but those will not allow me to control parameters of the new token.
What's the correct way to generate the token?
How about creating a service which creates and validates JWT?
#Service
public class TokenProvider {
public String createToken(User user) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + 5000); // Token will expire in 5 seconds
return Jwts.builder()
.setSubject(Long.toString(user.getId()))
.setIssuedAt(new Date())
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, "YOUR-SECRET-KEY")
.compact();
}
public Long getUserIdFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey("YOUR-SECRET-KEY")
.parseClaimsJws(token)
.getBody();
return Long.parseLong(claims.getSubject());
}
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey("YOUR-SECRET-KEY").parseClaimsJws(authToken);
return true;
} catch (SignatureException ex) {
logger.error("Invalid JWT signature");
} catch (MalformedJwtException ex) {
logger.error("Invalid JWT token");
} catch (ExpiredJwtException ex) {
logger.error("Expired JWT token");
} catch (UnsupportedJwtException ex) {
logger.error("Unsupported JWT token");
} catch (IllegalArgumentException ex) {
logger.error("JWT claims string is empty.");
}
return false;
}
}

Keycloak Admin API - How to check if password fits the password policy

I am using Keycloak admin API to create a new user.
How can I check that the given password indeed fits the realm password policy before creating the user?
I am using the following code:
Response response = usersResource.create(userRepresentation);
String userId = response.getLocation().getPath().replaceAll(".*/([^/]+)$", "$1");
UserResource userResource = usersResource.get(userId);
CredentialRepresentation passwordCred = new CredentialRepresentation();
passwordCred.setTemporary(false);
passwordCred.setType(CredentialRepresentation.PASSWORD);
passwordCred.setValue(somePassword);
userResource.resetPassword(passwordCred);
The problem with the above code is that the method "resetPassword" fails if the given password does not fit the password policy, but at this point the user has already been created in keycloak, and I have to delete it, since I have no way to "rollback".
The other option is to check is the password is OK before creating the user. But how can I do it?
You will get validation failure message as JSON Object some thing like this
{"error":"invalidPasswordMinLengthMessage","error_description":"Invalid password: minimum length 8."}
I used following code to read the validation failure message from the ClientErrorException
public void resetUserInvalidPassword() {
String userId = createUser("user1", "user1#localhost");
try {
CredentialRepresentation cred = new CredentialRepresentation();
cred.setType(CredentialRepresentation.PASSWORD);
cred.setValue(" ");
cred.setTemporary(false);
realm.users().get(userId).resetPassword(cred);
} catch (ClientErrorException e) {
Response response = e.getResponse();
System.out.println(getErrorMessage(response));
response.close();
}
}
private String getErrorMessage(Response response) {
Object entity = response.getEntity();
String errorMessage = "(none)";
if (entity instanceof ErrorRepresentation)
errorMessage = ((ErrorRepresentation) entity).getErrorMessage();
else if (entity instanceof InputStream)
errorMessage = new BufferedReader(new InputStreamReader((InputStream)entity)).lines().collect(Collectors.joining("\n"));
else if (entity != null)
errorMessage = entity.toString();
return errorMessage;
}
UserResource has the getUsers() method to find a user by username and check its attributes.
If the resetPassword failed, you could find the user, apply checks if needed, and resetPassword again.

Security Attacks possible on TokenBased Authentication?

I have designed a web application which uses very simple implementation of JWT token's to provide Authentication/Authorization.
My Implementation :
There are two types of urls's public and secure.
Public urls are to generate token with username/password.
I have added filter on secure url to check for the Authorization Header and JWT Token.
#Bean
public FilterRegistrationBean jwtFilter()
{
final FilterRegistrationBean registrationBean = new
FilterRegistrationBean();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/secure/*");
return registrationBean;
}
Filter will validate the token. I haven't added expiration date yet.
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
final String authHeader = request.getHeader("authorization");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(req, res);
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey(secretKey.toString).parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
chain.doFilter(req, res);
}
This is providing authentication and also its is immune to CSRF.No one can create valid token without secret Key.
Are there other attacks possible on token base authentication service which i have missed?

Google API consent screen not showing up on after publishing to server

I am working with the Google Provisioning API. I have used Web Application type project from Google developer console. I have used Diamto blog and samples and it works perfectly on my local with all options like FileStore, Custom File Store, Service Account etc but when I uploaded on server user consent screen just doesn't pops up with any options like FileStore, Custom File Store. I spent days to figure out problem and solutions but nothing has worked for me so far.
my configuration
My server configuration is windows server 2008 datacenter r2,.net 4.5,IIS 7.5.
Service account works perfectly but I need to do it by Consent screen so Web Application type of project.
I have used google .net client library with version 1.9.2.27817.
I am just highlighting main code where it gets stuck and rest is same as per Diamto post and github examples.
Let me know if you need more info.
Code
public static DirectoryService AuthenticateOauth(string clientId, string clientSecret, string userName, IDataStore datastore)
{
string[] scopes = new string[] {DirectoryService.Scope.AdminDirectoryUser };
try
{
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, datastore).Result; // at this point it calls getasynch method for custom datasource
DirectoryService service = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GoogleProv",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
{
HttpClientInitializer = credential,
ApplicationName = "GoogleProv",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
///<summary>
// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
// in <see cref="FolderPath"/> doesn't exist.
// </summary>
// <typeparam name="T">The type to retrieve</typeparam>
// <param name="key">The key to retrieve from the data store</param>
// <returns>The stored object</returns>
public Task<T> GetAsync<T>(string key)
{
//Key is the user string sent with AuthorizeAsync
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
// Note: create a method for opening the connection.
SqlConnection myConnection = new SqlConnection(myconn);
myConnection.Open();
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string RefreshToken = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
RefreshToken = myReader["RefreshToken"].ToString();
}
if (RefreshToken == null )
{
// we don't have a record so we request it of the user.
tcs.SetResult(default(T)); // it comes here
}
else
{
try
{
// we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
return tcs.Task; // it comes here and than gets hang forever
}
Any of your help is highly appreciated.

Securing a GWT app with a request param to be checked in a crosscontext attribute

My application is supposed to received a request parameter called sessionId which is supposed to be used to lookup for a crosscontext attribute.
I was looking at Spring Security to implement this and I think already have a good implementation of my AuthenticationProvider :
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
ServletContext servletContext = request.getSession().getServletContext();
String sessionId = request.getParameter("sessionId");
if (sessionId != null) {
ServletContext sc = request.getSession().getServletContext();
Object obj = sc.getContext("/crosscontext").getAttribute(sessionId);
if (obj != null) {
// return new Authentication
}
} else {
logger.error("No session id provided in the request");
return null;
}
if (!GWT.isProdMode()) {
// return new Authentication
} else {
logger.error("No session id provided in the request");
return null;
}
}
Now, what I would like to do is to configure Spring Security to not prompt for a user name and password, to let it reach this authentication provider call the authenticate method.
How can I achieve this ?
I fixed my issue by reviewing the design of my security and going for something closer to the preauthenticated mechanisms that are already provided by Spring Security.
I extended 2 components of Spring Security.
First one is an AbstractPreAuthenticatedProcessingFilter, usually his role is to provide the principal provided in the headers. In my case, I retrieve the header value and search in the context shared between 2 application for an attribute that corresponds to that header and returns it as principal :
public class MyApplicationPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
private static final Logger logger = Logger.getLogger(MyApplicationPreAuthenticatedProcessingFilter.class);
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
if (MyApplicationServerUtil.isProdMode()) {
String principal = request.getHeader("MY_HEADER");
String attribute = (String) request.getSession().getServletContext().getContext("/crosscontext").getAttribute(principal);
logger.info("In PROD mode - Found value in crosscontext: " + attribute);
return attribute;
} else {
logger.debug("In DEV mode - passing through ...");
return "";
}
}
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return null;
}
}
The other component is the AuthenticationProvider which will just check if the authentication contains a principal when it runs in prod mode (GWT prod) :
public class MyApplicationAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = Logger.getLogger(MyApplicationAuthenticationProvider.class);
public static final String SESSION_ID = "sessionId";
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (MyApplicationServerUtil.isProdMode()) {
if (StringUtils.isNotEmpty((String) authentication.getPrincipal())) {
logger.warn("Found credentials: " + (String) authentication.getPrincipal());
Authentication customAuth = new CustomAuthentication("ROLE_USER");
customAuth.setAuthenticated(true);
return customAuth;
} else {
throw new PreAuthenticatedCredentialsNotFoundException("Nothing returned from crosscontext for sessionId attribute ["
+ (String) authentication.getPrincipal() + "]");
}
} else {
Authentication customAuth = new CustomAuthentication("ROLE_USER");
customAuth.setAuthenticated(true);
return customAuth;
}
}
#Override
public boolean supports(Class<?> authentication) {
return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
}
}
I understand that it might not be the most secure application. However, it will already be running in a secure environment. But if you have suggestions for improvement, they're welcome !