Moinul Hossain
Moinul Hossain

Reputation: 2206

Spring Security 3 custom authentication requirement.... help needed!

I am developing an application with spring security. I have a requirement that when a user is created he is assigned a default password. The user must reset his password to have full access to his module. So after login in he wont be able to access any resource untill he changes his password.

I have a status flag in my database to keep track of whether the user is a new user or not. I also have a custom authentication provider that uses a custom JdbcDaoImpl

any clue on doing this please?

Upvotes: 1

Views: 591

Answers (2)

Stephen C
Stephen C

Reputation: 719709

You might want to revisit your requirements in the light of the following scenario:

  • Administrator creates a account for Fred with the default password.

  • Fred, being somewhat disinterested, doesn't try to login for a few days.

  • Meanwhile, Jim who knows (or has guessed) that Fred has a new account, logs in as Fred using the default password, resets it, and can now do things pretending to be Fred ... until Fred finally tries to use his account, and fails because he doesn't know the password.

You shouldn't use a default password. At the very least you should generate a random password for each new user and communicate it to the user by some (relatively) secure means.

Upvotes: 1

Pace
Pace

Reputation: 43957

It sounds like you have two different roles, ROLE_USER, and ROLE_NEW_USER. The trick is going to be configuring the interceptor to specify which roles you want. The interceptor's job is to identify resources you want to be secured and what roles are required to access them.

You don't specify so lets assume you're building a web application. By default you probably have some kind of FilterSecurityInterceptor. The configuration may look like...

This says that access to all URLs is secured and requires ROLE_USER. If your web application happened to have URLs that matched this use case you might be able to do something like...

Of course, if your web application isn't so happily structured then things get tricker. For example, maybe access to /updateConfig?newpassword=foobar is allowed so that the user can change their password but access to /updateConfig?username=newname should not be allowed.

In this case you're going to have to place the interceptor at a lower level. Perhaps you can use a MethodSecurityInterceptor to place access on your config service so that the setPassword method has ROLE_NEW_USER and the setName method has ROLE_USER. Just remember that MethodSecurityInterceptor is an aspect so if you have a ConfigService class with a setConfig, setPassword, and setName method and the web service calls setConfig which calls setPassword and setName then this won't work since aspects don't apply for method calls within a class.

In this case you'll probably want to write your own aspect that inspects the actual parameters getting passed into the method (this is naturally brittle so avoid it if you can). Or in the worst case you could check the security within the setName method itself (security is a cross-cutting concern and ideally should not be included within methods doing other things, this reduces cohesion since a method now has two responsibilities).

If you do roll your own interceptor you'll want to take a look at the SecurityContext class which provides you with the Authentication object for the current thread (e.g. request).

You'll also need to modify your UserService implementation so that it when it provides users it sets the role appropriately (ROLE_USER or ROLE_NEW_USER based on the database tag).

Last but not least you'll want to figure out how your application deals with authentication failures. In the web service example you could redirect your users to a change password page if they ever fail authentication. Of course, it might get tricky to redirect them to a change password page if they are a ROLE_NEW_USER and a register page if they have no role.

Upvotes: 4

Related Questions