Spring MVC Web Request and Android Request to Same Method - java

I have an spring mvc web application in which users login to session "session.setAttribute" classically. Whenever I need loggedin user data I use this data.
Now I want to add android app and what I want to learn do I have to add additional methods for each android request and send user data within it?
Or Is there away to make a request to same methods.
What is the consept for this kind of cloud apps? Do I have to write different methods for android requests? Because it is not possible session.getAttribute when wemake an android request, it returns null.
User user = userService.getByUserNameAndPassword(userName, password);
if (user != null) {
if (user.isActive()) {
Account account = new Account(user, request.getRemoteAddr());
HttpSession httpSession = request.getSession(true);
AccountRegistry.add(httpSession);
httpSession.setAttribute(Constant.ACCOUNT, account);
result.put(Constant.REF, Constant.SUCCESS);
}
public class Account {
private UserRightsHandler userRightsService = null;
private User user;
private String ipAddress;
private boolean admin;
public Account(User user, String ipAddress) {
this.user = user;
this.ipAddress = ipAddress;
userRightsService = new UserRightsHandler(user);
setAdmin(userRightsService.isAdmin());
}
public UserRightsHandler getUserRightsService() {
return userRightsService;
}
public User getUser() {
return this.user;
}
public String getIpAddress() {
return ipAddress;
}
public boolean isAdmin() {
return admin;
}
private void setAdmin(boolean admin) {
this.admin = admin;
}
}
public class AccountRegistry {
private static final Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
public static void add(HttpSession session) {
sessions.put(session.getId(), session);
}
public static void remove(HttpSession session) {
if (session != null) {
sessions.remove(session.getId());
session.setAttribute(Constant.ACCOUNT, null);
session.invalidate();
}
}
public static HttpSession getByHttpSessionID(String httpSessionID) {
Set<String> keys = sessions.keySet();
Iterator it = keys.iterator();
while (it.hasNext()) {
String sID = (String) it.next();
HttpSession session = sessions.get(sID);
if (sID.equals(httpSessionID)) {
return session;
}
}
return null;
}
public static void removeByHttpSessionID(String httpSessionID) {
HttpSession session = getByHttpSessionID(httpSessionID);
remove(session);
}
public static Account getCurrentAccount() {
HttpServletRequest request = ContextFilter.getCurrentInstance().getRequest();
HttpSession session = request.getSession();
return (Account) session.getAttribute(Constant.ACCOUNT);
}
}
#RequestMapping(value = "/changeStatus", method = RequestMethod.POST)
public #ResponseBody
String changeStatus(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
User editor = AccountRegistry.getCurrentAccount().getUser();
}

You can ask user send their user and password at the start of Android app via custom authenticate request like /appLogin then if it is correct creditentals you can return a key to user (to app) and store it to some variable during app run. Then when user want to do something send a request to server you can send it to a function with mapping like /appExampleService then you can check at that function this key and device valid depending on how you handle custom login process then this function call existing function that is used for web browsers that have mapping /exampleService. For example;
#JsonSerialize
#RequestMapping("/appExampleService")
public int someServiceForAppClient(
#RequestParam(value = "key", required = true) String apikey,
#RequestParam(value = "param", required = true) String someParam{
String name=userDAO.getUsernameFromApiKey(apikey);
return someService(someParam, name);
}
#JsonSerialize
#RequestMapping("/exampleService")
public int someServiceForWebClient(
#RequestParam(value = "param", required = true) String someParam) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
return someService(someParam, name);
}
public int someService(String someParam,String name){
return doBusiness(someParam, name);
}
userDAO is just something I created for to get info of user with given key. And there is a service for App login as well which return that key to user when he started the app send his username and pass

Related

Can I set additional parameters of spring boot with groovy?

I am new to groovy and spring boot.I start to work on login with spring boot.
I need to pass two additional parameters to the CustomAuthToken class.
I can pass only one.When I assign other variable to some value auth fail.
This is my code.
CustomAuthFilter.groovy
Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.post) {
throw new AuthenticationServiceException("not supported: $request.method")
}
String username = (obtainUsername(request) ?: '').trim()
String password = (obtainPassword(request) ?: '').trim()
String extrafield1 = request.getParameter("extrafield1")
String extrafield2 = request.getParameter("extrafield2")
def authentication = new CustomAuthToken(username, password, extrafield1, null, false, false, false)
HttpSession session = request.getSession(false)
if (session || getAllowSessionCreation()) {
request.session['SPRING_SECURITY_LAST_USERNAME_KEY'] = TextEscapeUtils.escapeEntities(username)
}
return getAuthenticationManager().authenticate(authentication)
}
CustomAuthToken.groovy
CustomAuthToken(Object principal, Object credentials, String extrafield1, String PVM, Boolean isAccept, Boolean isLogEnabled, Boolean is3PLEnabled) {
super(principal, credentials)
extra1 = extrafield1
}
It is working and I can access the extra1 field.
But when I try to pass anther parameter it's not working.
CustomAuthToken(Object principal, Object credentials, String extrafield1, String extrafield2, String PVM, Boolean isAccept, Boolean isLogEnabled, Boolean is3PLEnabled) {
super(principal, credentials)
extra1 = extrafield1
extra2 = extrafield2
}
When I try this extra2 is passing. But auth is fail.
Can anyone have an idea about this?
My guess is that
CustomAuthToken extends UsernamePasswordAuthenticationToken
If that's the case, you need to change the super constructor call from
super(principal, credentials)
to
super(principal, credentials, Collections.emptyList())
You see, the constructor you are invoking sets authenticated=false
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
So you want to invoke the correct constructor
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true); // must use super, as we override
}

Creating JSON Web Tokens through Basic Authentication endpoint? Dropwizard

Using Dropwizard 1.2.0 and Dropwizard JWT library, I am trying to create json web tokens from an API endpoint called /token
This endpoint requires the client to pass a username and password, using Basic Authentication method. If successful the response will contain a JSON web token.
Principal
public class ShepherdAuth implements JwtCookiePrincipal {
private String name;
private Set<String> roles;
public ShepherdAuth(String name, Set<String> roles) {
this.name = checkNotNull(name, "User name is required");
this.roles = checkNotNull(roles, "Roles are required");
}
#Override
public boolean isPersistent() {
return false;
}
#Override
public boolean isInRole(final String s) {
return false;
}
#Override
public String getName() {
return this.name;
}
#Override
public boolean implies(Subject subject) {
return false;
}
public Set<String> getRoles() {
return roles;
}
}
Authenticator
public class ShepherdAuthenticator implements Authenticator<BasicCredentials, ShepherdAuth> {
private static final Map<String, Set<String>> VALID_USERS = ImmutableMap.of(
"guest", ImmutableSet.of(),
"shepherd", ImmutableSet.of("SHEPHERD"),
"admin", ImmutableSet.of("ADMIN", "SHEPHERD")
);
#Override
public Optional<ShepherdAuth> authenticate(BasicCredentials credentials) throws AuthenticationException {
if (VALID_USERS.containsKey(credentials.getUsername()) && "password".equals(credentials.getPassword())) {
return Optional.of(new ShepherdAuth(credentials.getUsername(), VALID_USERS.get(credentials.getUsername())));
}
return Optional.empty();
}
}
Resource / Controller
public class ShepherdController implements ShepherdApi {
public ShepherdController() {
}
#PermitAll
#GET
#Path("/token")
public ShepherdAuth auth(#Auth final BasicCredentials user) {
return new ShepherdAuth(user.getUsername(),
ImmutableSet.of("SHEPHERD"));
}
App / Config
#Override
public void run(final ShepherdServiceConfiguration configuration,
final Environment environment) {
final ShepherdController shepherdController = new ShepherdController();
// app authentication
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<ShepherdAuth>()
.setAuthenticator(new ShepherdAuthenticator())
.setAuthorizer(new ShepherdAuthorizer())
.setRealm(configuration.getName())
.buildAuthFilter()));
When I try to make a request to /shepherd/token I do not get a prompt for basic auth, instead I get a HTTP 401 response with
Credentials are required to access this resource.
How do I get the controller to prompt for username and password and generate a JWT on success?
I implemented JWT tokens in my project by using https://github.com/jwtk/jjwt but the solution will easily be applied to another library. The trick is to use different authenticators.
This answer is not suited for Dropwizard JWT Library but does the fine job of providing JWT for Dropwizard :)
First, the application:
environment.jersey().register(new TokenResource(configuration.getJwsSecretKey()));
environment.jersey().register(new HelloResource());
environment.jersey().register(RolesAllowedDynamicFeature.class);
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
environment.jersey()
.register(
new AuthDynamicFeature(
new ChainedAuthFilter<>(
Arrays
.asList(
new JWTCredentialAuthFilter.Builder<User>()
.setAuthenticator(
new JWTAuthenticator(configuration.getJwsSecretKey()))
.setPrefix("Bearer").setAuthorizer(new UserAuthorizer())
.buildAuthFilter(),
new JWTDefaultCredentialAuthFilter.Builder<User>()
.setAuthenticator(new JWTDefaultAuthenticator())
.setAuthorizer(new UserAuthorizer()).setRealm("SUPER SECRET STUFF")
.buildAuthFilter()))));
Please note that the configuration class must contain a configuration setting:
String jwsSecretKey;
Here, the TokenResource is the token supplying resource, and the HelloResource is our test resource. User is the principal, like this:
public class User implements Principal {
private String name;
private String password;
...
}
And there is one class for communicating the JWT token:
public class JWTCredentials {
private String jwtToken;
...
}
TokenResource provides tokens for a user "test" with password "test":
#POST
#Path("{user}")
#PermitAll
public String createToken(#PathParam("user") String user, String password) {
if ("test".equals(user) && "test".equals(password)) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(this.secretKey);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
JwtBuilder builder = Jwts.builder().setIssuedAt(now).setSubject("test")
.signWith(signatureAlgorithm, signingKey);
return builder.compact();
}
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
And the HelloResource just echoes back the user:
#GET
#RolesAllowed({"ANY"})
public String hello(#Auth User user) {
return "hello user \"" + user.getName() + "\"";
}
JWTCredentialAuthFilter provides credentials for both authentication schemes:
#Priority(Priorities.AUTHENTICATION)
public class JWTCredentialAuthFilter<P extends Principal> extends AuthFilter<JWTCredentials, P> {
public static class Builder<P extends Principal>
extends AuthFilterBuilder<JWTCredentials, P, JWTCredentialAuthFilter<P>> {
#Override
protected JWTCredentialAuthFilter<P> newInstance() {
return new JWTCredentialAuthFilter<>();
}
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final JWTCredentials credentials =
getCredentials(requestContext.getHeaders().getFirst(HttpHeaders.AUTHORIZATION));
if (!authenticate(requestContext, credentials, "JWT")) {
throw new WebApplicationException(
this.unauthorizedHandler.buildResponse(this.prefix, this.realm));
}
}
private static JWTCredentials getCredentials(String authLine) {
if (authLine != null && authLine.startsWith("Bearer ")) {
JWTCredentials result = new JWTCredentials();
result.setJwtToken(authLine.substring(7));
return result;
}
return null;
}
}
JWTAuthenticator is when JWT credentials are provided:
public class JWTAuthenticator implements Authenticator<JWTCredentials, User> {
private String secret;
public JWTAuthenticator(String jwtsecret) {
this.secret = jwtsecret;
}
#Override
public Optional<User> authenticate(JWTCredentials credentials) throws AuthenticationException {
try {
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(this.secret))
.parseClaimsJws(credentials.getJwtToken()).getBody();
User user = new User();
user.setName(claims.getSubject());
return Optional.ofNullable(user);
} catch (#SuppressWarnings("unused") ExpiredJwtException | UnsupportedJwtException
| MalformedJwtException | SignatureException | IllegalArgumentException e) {
return Optional.empty();
}
}
}
JWTDefaultAuthenticator is when no credentials are present, giving the code an empty user:
public class JWTDefaultAuthenticator implements Authenticator<JWTCredentials, User> {
#Override
public Optional<User> authenticate(JWTCredentials credentials) throws AuthenticationException {
return Optional.of(new User());
}
}
UserAuthorizer permits the "ANY" role, as long as the user is not null:
public class UserAuthorizer implements Authorizer<User> {
#Override
public boolean authorize(User user, String role) {
return user != null && "ANY".equals(role)
}
}
If all goes well,
curl -s -X POST -d 'test' http://localhost:8080/token/test
will give you something like:
eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY
and this query
curl -s -X POST -d 'xtest' http://localhost:8080/token/test
will fail with
{"code":401,"message":"HTTP 401 Unauthorized"}
(BTW, "test" in the URL is the user name and "test" in the post data is the password. As easy as basic auth, and can be configured for CORS.)
and the request
curl -s -X GET -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY' http://localhost:8080/hello
will show
hello user "test"
while
curl -s -X GET -H 'Authorization: Bearer invalid' http://localhost:8080/hello
and
curl -s -X GET http://localhost:8080/hello
will result in
{"code":403,"message":"User not authorized."}
Your missing this line in your configuration.
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));

Get user in a Rest Controller class instead of each controller method

I have a #RestController with bunch of Rest endpoints as methods.
#RequestMapping(path="",method=RequestMethod.POST)
public void create(Principal principal) {
String userName = principal.getName();
User user = UsersRepository.loadUser(userName);
//....
}
#RequestMapping(path="/{groupId}",method=RequestMethod.DELETE)
public void deleteGroup(#PathVariable String groupId, Principal principal) {
String userName = principal.getName();
User user = UsersRepository.loadUser(userName);
//....
}
In each method I have to repeat this code:
String userName = principal.getName();
User user = UsersRepository.loadUser(userName);
Is there a way not to repeat this in each method and get it in the class, and consume it in each method ?
1) Very basic but why not simply extract it in a private method :
public User getUser(Principal principal){
String userName = principal.getName();
User user = UsersRepository.loadUser(userName);
//....
return user;
}
You could write so :
#RequestMapping(path="",method=RequestMethod.POST)
public void create(Principal principal) {
User user = getUser(principal);
//....
}
2) More advanced : you could use a Spring interceptor that reads in the request, loads the user and wires it in a bean with a request scope.

How to bind the session to the User object using jersey

I am trying to create login function and I want to save in the session specific data to use in future requests of the user is it possible?
In the loginUser, first if is always false even if the user already logged
and same in the updatePassword .
I need to save the attribute from the function loginUserToSession. Any idea why it doesn't work ?
here is my code
Resource
#Path("/logIn")
#Singleton
public class UserResource extends baseResource<UserDao, UserEntity>
{
#Path("/authenticateUser")
#GET
#UnitOfWork
public String loginUser(#Context HttpServletRequest req #QueryParam("callback") String callback, #QueryParam("loginInfo") LoginInfo loginInfo) throws JsonProcessingException
{
if(SessionManager.isUserConnected(req))
{
return ResourceResponse.getResourceJsonString("null", callback, "true", ErrorMessageEnum.SUCCESS);
}
String userName = loginInfo.username;
String plainTextPassword = loginInfo.password;
UserEntity user = objectDao.logIn(userName, plainTextPassword);
if(user != null)
{
SessionManager.loginUserToSession(req, user.getUserId(), userName);
return ResourceResponse.getResourceJsonString(user.getUserStatus(), callback, "true", ErrorMessageEnum.SUCCESS);
}
return ResourceResponse.getResourceJsonString("null", callback, "false", ErrorMessageEnum.LOGIN_FAILED);
}
#Path("/updatePassword")
#GET
#UnitOfWork
public String updatePassword(#Context HttpServletRequest req, #QueryParam("callback") String callback, #QueryParam("oldPwd") String oldPwd, #QueryParam("newPwd") String newPwd) throws JsonProcessingException
{
if(SessionManager.isUserConnected(req))
{
short userId = SessionManager.getUserId(req);
ObjectDaoResponse res = objectDao.updatePassword(userId, oldPwd, newPwd);
return ResourceResponse.getResourceJsonString(res.getObjectJsonString(), callback, res.getSuccess(), res.getCode());
}
else
{
return ResourceResponse.getResourceFailResponseString(callback, ErrorMessageEnum.USER_NOT_CONNECTED);
}
}
}
SessionManager.java
public static void loginUserToSession(HttpServletRequest req, short userId, String userName)
{
if(req == null)
{
return;
}
HttpSession session = req.getSession(true);
session.setAttribute(ATTRIBUTE_USER_NAME, userName);
session.setAttribute(ATTRIBUTE_USER_ID, userId);
session.setAttribute(ATTRIBUTE_USER_CONNECTED, true);
}
public static boolean isUserConnected(HttpServletRequest req)
{
if(req == null)
{
return false;
}
HttpSession session = req.getSession(false);
if(session != null)
{
boolean userConnected = (boolean) session.getAttribute(ATTRIBUTE_USER_CONNECTED);
if(userConnected)
{
return userConnected;
}
System.out.Println("session.getAttribute(ATTRIBUTE_USER_CONNECTED)== null");
}
return false;
}
Please change into Resource like this:
public String loginUser(#Context HttpServletRequest req #QueryParam("callback") String callback, #QueryParam("loginInfo") LoginInfo loginInfo) throws JsonProcessingException
{
if(SessionManager.isUserConnected(req))
{
return ResourceResponse.getResourceJsonString("null", callback, "true", ErrorMessageEnum.SUCCESS);
}else{
String userName = loginInfo.username;
String plainTextPassword = loginInfo.password;
UserEntity user = objectDao.logIn(userName, plainTextPassword);
if(user != null)
{
SessionManager.loginUserToSession(req, user.getUserId(), userName);
return ResourceResponse.getResourceJsonString(user.getUserStatus(), callback, "true", ErrorMessageEnum.SUCCESS);
}
}
}
Above was the flow error , whatever i got, Now you have to setattribute into session scope then use this:
HttpSession session = request.getSession();
session.setAttribute("UserName", "Usename_Value");
Or for request Scope use this:
request.setAttribute("attributeName",yourStringVAlue);
It turns out that for some reason google postman don't send the HttpServletRequest as it should be. so jersey translate it like new user and create an empty new HttpServletRequest. Conclusion do not test your server side with Google's postman
when i try to send the request from my client it work fine.

Please ensure that at least one realm can authenticate these tokens

So I have set up my shiro to have two Realms. A Username and Password Realm, using the standard UsernamePasswordToken. I have also set up a Custom Bearer Authentication Token that works off a token passed in from the user.
If i just use my passwordValidatorRealm it works find, if no user is found throws unknown account, if password doesn’t match throws incorrect credentials, perfect. But as soon as i put in my tokenValidatorRealm it throws a
org.apache.shiro.authc.AuthenticationException: Authentication token of type [class org.apache.shiro.authc.UsernamePasswordToken] could not be authenticated by any configured realms.
In this instance my tokenValidatorRealm returns null as no token was provided, so it moves on to the passwordValidatorRealm and just breaks.
Any ideas why introducing a second Realm will cause my working passwordValidatorRealm to break?
Have tried with different authentication strategies, and no luck there.
Using shiro 1.2.2
EDIT
I have two implementations, one for password and one for token
Password:
public class PasswordAuthorizingRealm extends AuthenticatingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (authenticationToken instanceof UsernamePasswordToken) {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
String username = usernamePasswordToken.getUsername();
char[] password = usernamePasswordToken.getPassword();
if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm!");
}
//Null password is invalid
if (password == null) {
throw new AccountException("Null passwords are not allowed by this realm!");
}
UserService userService = new UserServiceImpl();
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UnknownAccountException("Could not authenticate with given credentials");
}
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(), "passwordValidatorRealm");
return simpleAuthenticationInfo;
} else {
return null;
}
}
}
and Bearer Token
public class TokenAuthorizingRealm extends AuthorizingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (authenticationToken instanceof BearerAuthenticationToken) {
BearerAuthenticationToken bearerAuthenticationToken = (BearerAuthenticationToken) authenticationToken;
String username = "" + bearerAuthenticationToken.getPrincipal();
User user = userService.getUserByUsername(username);
//User with such username has not found
if (user == null) {
throw new UnknownAccountException("Could not authenticate with given credentials");
}
BearerAuthenticationInfo bearerAuthenticationInfo = new BearerAuthenticationInfo(user);
return bearerAuthenticationInfo;
}
}
Shiro config
[main]
hashService = org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations = 500000
hashService.hashAlgorithmName = SHA-256
hashService.generatePublicSalt = true
hashService.privateSalt = ****
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordService.hashService = $hashService
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService
authc = my.BearerTokenAuthenticatingFilter
tokenValidatorRealm = my.TokenAuthorizingRealm
passwordValidatorRealm = my.PasswordAuthorizingRealm
passwordValidatorRealm.credentialsMatcher = $passwordMatcher
securityManager.realms = $tokenValidatorRealm,$passwordValidatorRealm
These have been stripped out a bit, removed logging and other unnecessary code
The BearerTokenAuthenticatingFilter, just basically checks if a token has been supplied in the header if has
private void loginUser(ServletRequest request, ServletResponse response) throws Exception {
BearerAuthenticationToken token = (BearerAuthenticationToken) createToken(request, response);
if (token == null) {
String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken "
+ "must be created in order to execute a login attempt.";
throw new IllegalStateException(msg);
}
try {
Subject subject = getSubject(request, response);
subject.login(token);
onLoginSuccess(token, subject, request, response);
} catch (AuthenticationException e) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.sendRedirect("login");
}
}
BearerAuthenticationInfo class
public class BearerAuthenticationInfo implements AuthenticationInfo {
private final PrincipalCollection principalCollection;
private final User user;
public BearerAuthenticationInfo(User user) {
this.user = user;
this.principalCollection = buildPrincipalCollection(user);
}
public PrincipalCollection getPrincipals() {
return principalCollection;
}
public Object getCredentials() {
return user.getUsername();
}
private PrincipalCollection buildPrincipalCollection(User user) {
Collection<String> principals = new ArrayList<String>();
principals.add(user.getUsername());
return new SimplePrincipalCollection(principals, "tokenValidatorRealm");
}
}
Looks like it is expected behavior.
If you look at the javadoc for ModularRealmAuthenticator:
* #throws AuthenticationException if the user could not be authenticated or the user is denied authentication
* for the given principal and credentials.
*/
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
If you are having problems with the exception, you might need to change the code that calls the authentication to expect this exception.
Left for other searches:
You might have a missing supports method in your TokenAuthorizingRealm class.
Something like
#Override
public boolean supports(AuthenticationToken token) {
return token instanceof BearerAuthenticationToken;
}
should be present.
This discussion help me solve a similar problem. I wanted to authenticate a user by the application itself, not using any Shiro default implementation. To do that we must subclass AuthenticatingRealm, override doGetAuthenticationInfo and declare this realm as the validation one.
public class PasswordAuthorizingRealm extends AuthenticatingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
In Shiro.ini:
passwordValidatorRealm = my.PasswordAuthorizingRealm

Categories