Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Álvaro Sánchez-Mariscal
@alvarosanchez
@nikuelias tienes que implementar tu propia versión de org.springframework.security.web.authentication.AuthenticationFailureHandler, y registrarla en resources.groovy como restAuthenticationFailureHandler
sbrady
@sbrady
Hi All, I am attempting to run the test-app.sh, I keep getting:
| Error Compilation error compiling [unit] tests: (class: com/odobo/grails/plugin/springsecurity/rest/RestAuthenticationToken, method: super$1$implies signature: (Ljavax/security/auth/Subject;)Z) Illegal use of nonvirtual function call (Use --stacktrace to see the full trace)
I am using Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
maybe its a groovy version issue?
sbrady
@sbrady
never mind grails clean seemed to fix it
sbrady
@sbrady
Hey @alvarosanchez , thanks for the release
I have a question/suggestion re rfc6750, I think when a user makes a request to a secured url with out any token, it should respond with a 401, (https://tools.ietf.org/html/rfc6750#section-3.1)
I'd expect to get a 403, when I have an authenticated token but my access scope is forbidden
prdonahue
@prdonahue
anyone here having trouble implementing the anonymous example in the docs?
i just wrote a (pretty meaty) explanation here: alvarosanchez/grails-spring-security-rest#122
nikuelias
@nikuelias
Hola Alvaro, soy yo nuevamente. Gracias por contestarme la vez pasada. Tengo una nueva duda. Quiero filtrar los usuarios que pueden loguearse. Para eso, me parece que lo que debería hacer es reescribir la clase "RestAuthenticationFIlter.groovy" verdad? Si es así, como debería hacerlo? Crear en mi carpeta src/groovy un package con el mismo nombre y una clase con el mismo nombre y sobreescribir el metodo Do FIlter? O lo estoy haciendo mal? Ya que no estoy logrando poder capturar el evento. Me da constantemente errores de java. Bueno espero su respuesta, espero haber sido claro. Además de esto, debería escribir algo en resources.groovy? Gracias desde ya, Nicolas.
Álvaro Sánchez-Mariscal
@alvarosanchez
@sbrady I addressed that issue in the latest release, I think
@nikuelias please better write in English on this channel, so that everybody can understand and/or help. Regarding your question, not sure what do you mean by "filter users". Could you clarify that?
nikuelias
@nikuelias

Sorry. I will give a try in english :). I want to do this:

When a user logs in, I want to check some data to let him log in or not. I need to create user with "expiration date" so when the users logs in, i need to check if the date is between startDate and endDate. To do this, i thought to check this data in the RestAuthenticationFilter. So, to do thi i dont really know how to. Do I need to create a class with the same name and package en my project? Because when I do this, all kinds of errors appear in my project. And, i think, I should modify resources.groovy but i dont really know how to either. Hope you can help me and understand me. Thanks a lot Alvaro.

sbrady
@sbrady
@alvarosanchez if I look at the BearerTokenSpec.groovy, it expects 403 In some places, where is should probably be 401...I think
Álvaro Sánchez-Mariscal
@alvarosanchez
@nikuelias assuming you are using GORM for storing users, you can subclass DaoAuthenticationProvider
eg
class ExpiringUsersAuthenticationProvider extends DaoAuthenticationProvider
and then override additionalAuthenticationChecks()
void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    super.additionalAuthenticationChecks(userDetails, authentication)

    //... your code ...
}
finally, you have to register the bean in resources.groovy
Álvaro Sánchez-Mariscal
@alvarosanchez
        daoAuthenticationProvider(ExpiringUsersAuthenticationProvider) {
            userDetailsService = ref('userDetailsService')
            passwordEncoder = ref('passwordEncoder')
            userCache = ref('userCache')
            saltSource = ref('saltSource')
            preAuthenticationChecks = ref('preAuthenticationChecks')
            postAuthenticationChecks = ref('postAuthenticationChecks')
            authoritiesMapper = ref('authoritiesMapper')
            hideUserNotFoundExceptions = SpringSecurityUtils.securityConfig.dao.hideUserNotFoundExceptions // true
        }
Álvaro Sánchez-Mariscal
@alvarosanchez
@sbrady let me have a closer look
nikuelias
@nikuelias
Thanks a lot @alvarosanchez i will try and give an update to you!
Todsaporn Sangboon
@nolifelover
I have some trouble about loop on filter from spring-security-rest, on each request it take long time to process and render view. after enable logging, I found getReachableGrantedAuthorities() many time call. I post new issue on alvarosanchez/grails-spring-security-rest#148
Thank you and apologize for my english.
dbknickerbocker
@dbknickerbocker

Version 1.4.1.RC2, due to implementation of 'Major overhaul to be less aggressive when handling bearer tokens', RestTokenValidationFilterSpec.groovy now returns 403 instead of 401 for requests where 'X-Auth-Token' header is missing or empty.

This is a breaking change for my single page application where I key off the 401 to show the login page.
@alvarosanchez - Was this change intentional as I didn't see any notes about it in the documentation.

As a developer having the 401 was immensely valuable to me.

sbrady
@sbrady
@dbknickerbocker I just submitted a PR alvarosanchez/grails-spring-security-rest#150
dbknickerbocker
@dbknickerbocker
@sbrady What about the non-bearer token case?
sbrady
@sbrady
@dbknickerbocker on I didn't even consider that, sorry
Álvaro Sánchez-Mariscal
@alvarosanchez
I think the mentioned PR needs further discussion
is not that simple
Florent Blanvillain
@florent-blanvillain
@alvarosanchez I'm interested in the switch-user functionality, as discussed in alvarosanchez/grails-spring-security-rest#125. However I unfortunately need it now :-D More seriously, could you give me some precise pointers to do the simplest switch user functionality possible ? I don't need to be able to switch back, I don't even need to know that the current user has been switched to. All I need is for an admin user to be (re)authenticated as a given other user with its username via a POST. From what you describe as what would be necessary to implement the switch-user-spring-security-like functionality, I guess the authentication as another user is not the most complex part; but I have no idea where to begin with. Thanks a lot and sorry..
Yanis Ikene
@yanisIk

Hello Alvaro, first I would like to thank you for this wonderful plugin.
However, your plugin doesn't answer to all my needs so I decided to modify it and I want to ask you if this is correct and if you can do it in a future release too.

So, what I need is OAuth but with the client sending the oauth token (for usage with a mobile app for example). Your plugin only allows to OAuth with a website client side, but not with other type of clients like mobile apps.
So here's the new flow :

1) Client authenticate to provider and receives informations.
2) Client login to our grails app : api/authenticate/{provider}
3) The modified RestOAuthController does the following :

    @Secured(['permitAll'])
class RestOauthController extends RestController{
    static responseFormats = ['json']
    static allowedMethods = [authenticate: "POST"]

    def restOauthService

    //Client OAuth flow only
    def authenticate(String provider){

        BaseOAuthClient client = restOauthService.getClient(provider)
        WebContext context = new J2EContext(request, response)

        try {
                String tokenValue = restOauthService.storeAuthentication(provider, context)
        } 
        catch (Exception e) {
                String errorParams
                if (e instanceof UsernameNotFoundException) {
                    restOauthService.registerUser(provider, context) 
                    //Is this necessary or is it already done in DefaultOauthUserDetailsService in catch (UsernameNotFoundException unfe) log.debug "User not found. Creating a new one with default roles: ${defaultRoles}"
                } else {
                    respond ["error" : "&error=${e.cause?.code?:500}&message=${e.message?.encodeAsURL()?:''}"]
                }
        }
        log.debug "Returning access_token in json"
        respond [''access_token'' : tokenValue]
    }    
    }
}
Yanis Ikene
@yanisIk

4) The client sends back this token in each request

My questions :
1) How do I access the logged user (MyUser not Spring's User) in a controller :
Example :

  class MyUser{
        User user //Spring security User
        static hasOne = ['user']
        static hasMany = [dogs : Dog]
  }
  class Dog{
        MyUser owner
        String name
        static belongsTo = ['owner']
   }
  class DogRestController extends RestController{
        .....
        @Secured['ROLE_USER']
         def index(){
             MyUser myUser = getAuthenticatedUser() //Spring security metaclass method
              //Will this map correctly the User to MyUser ? is my domain well defined ? 
             respond Dog.findAllByOwner(myUser)
          } 
    }
Yanis Ikene
@yanisIk

I also modified RestOauthService to create a new MyUser when this is the first time OAuth Login/Signup

String storeAuthentication(String provider, WebContext context) {
    .......
    try{
            //is created even if first time login/signup
    OauthUser userDetails = oauthUserDetailsService.loadUserByUserProfile(profile, defaultRoles)
}
catch (UsernameNotFoundException unfe) {
    log.debug "MyUser not found. Creating a new one"
    registerMyUser(userDetails)
}
     ....
}

/** Register a new MyUser with the informations contained in OAuth profile **/
@Transactional
def registerMyUser(OauthUser user){

CommonProfile profile = user.userProfile

Address address = new Address(city: profile.location)
Profile profile = new Profile(name:profile.displayName, emailAddress:profile.email, photoUrl:profile.pictureUrl, address:address )

HobdyUser hobdyUser = new HobdyUser(user: user, profile: profile)

hobdyUser.save() //Do not flush
}    

Is this the correct way to do it ?

Thanks.

Florent Blanvillain
@florent-blanvillain

Following my question, I think I found the answer and it was incredibly simple !!
Here is a controller's action that seems to do the job:

def switchUser() {
    def username = params.username
    def principal = userDetailsService.loadUserByUsername(username)
    if (principal) {
        def oldToken = request.getHeader("X-Auth-Token")
        tokenStorageService.removeToken(oldToken)

        def newToken = new SecureRandomTokenGenerator().generateToken()
        tokenStorageService.storeToken(newToken, principal)
        render(contentType: "text/json") {
            [
                    username    : username,
                    roles       : principal.authorities.authority,
                    access_token: newToken
            ]
        }
    } else {
        render status: 404
    }
}

Thanks

Yanis Ikene
@yanisIk
I also found something exploitable : Let's say I signup with OAuth, then a user will be created with my id and no password. Then let's say I login after that using /api/login and just enter my id and N/A password, will it login ? Do I have to modify the login controller too ?
Álvaro Sánchez-Mariscal
@alvarosanchez
@florent-blanvillain you should have a look at #131. There is lots of useful information there
@florent-blanvillain ok, I just read your latest comment :) Few comments on your code
1) To get the current principal you don't need to load it again. Just use springSecurityService.principal (inject that bean in your controller)
2) The header name can be customised in Config.groovy, so you better don't hardcode it just in case
3) Inject tokenGenerator bean instead of manually building an instance of one of them
Oh, forget about 1), I just realised is not the current principal, but the new one...
Álvaro Sánchez-Mariscal
@alvarosanchez
@skini26 about the OAuth delegation support, it is only for web based applications because I use the implicit grant support of those providers
To access the current user you can use springSecurityService.currentUser
Regarding the exploit you mention, if you are not using it, you can disable the login endpoint. Otherwise, you should have to generate a random password to avoid that
Florent Blanvillain
@florent-blanvillain
@alvarosanchez thanks :-D
Yanis Ikene
@yanisIk

@alvarosanchez thanks :) (I know the code I wrote has a lot of wrong things, sorry about that, I just figured them out after but I can't edit anymore).

Another question : Is there a controller already available for registering users ? I found nothing in SS core, maybe I missed it.
And the springSecurityService.currentUser will return me the Spring Security User and not my custom User. So do you suggest me to modify the generated User by SpringSecurity Core (as suggested by their documentation), or to extend it or to have a reference to it ?

Thanks.

Álvaro Sánchez-Mariscal
@alvarosanchez
@skini26 springSecurityService.currentUser should return your DB user. The other one is springSecurityService.principal. Have you tried both to see the results?
Robert Oschwald
@robertoschwald
Hi Alvaro. Thanks for your plugin. Just a quick note: I use your plugin for IOS App REST Auth to a Grails server application, so the scope of the plugin is much wider than just decoupling HTML frontends.