passport-oauth2 icon indicating copy to clipboard operation
passport-oauth2 copied to clipboard

Passing user specified parameter to authorizationParams()

Open soichih opened this issue 7 years ago • 5 comments

Hello.

My oauth2 provider handles multiple idP(s), and I can specify which one to use by setting "selected_idp" parameter to authorize URL

http://www.cilogon.org/oidc

I see that I can add arbitrary parameters to authorize URL by overriding authorizationParams() function, but this function doesn't allow accessing user request parameter.

Can you add an additional option parameter to authenticate() so that I could do something like

router.get('/signin', function(req, res, next) {
    passport.authenticate('oauth2', {
        authorize_params: function() {
            return {selected_idp: req.query.idp}
        }
    })(req, res, next);
});

??

soichih avatar Mar 31 '17 14:03 soichih

I just realized I could do this instead

OAuth2Strategy.prototype.authorizationParams = function(options) {
    return { selected_idp: options.idp }
}
router.get('/signin', function(req, res, next) {
    passport.authenticate('oauth2', {
        //this will be used by my authorizationParams() and selected_idp will be injected to authorized url
        idp: req.query.idp
    })(req, res, next);
});

Is there any side effect from Javascript closure?

soichih avatar Mar 31 '17 15:03 soichih

+1 for a way to allow arbitrary parameters in the authorisation URL. For instance, if req could be passed to the call to authorizationParams (eg https://github.com/jaredhanson/passport-oauth2/blob/master/lib/strategy.js#L216) would allow returning params and values based upon the request, session, user etc. In my use case, my OAuth provider takes a variety of different parameters and because I'm authorize()'ing an existing user, I'd want to pass the user's attributes (from the request session).

What @soichih suggests with authenticate() is an option -- perhaps a second level of customisation -- but at least initially it having the Strategy pass the request to its authorizationParams function would make it simpler than having to create separate closures/callbacks.

davidjb avatar Sep 15 '17 02:09 davidjb

Agreed, and there is also the claims parameter which doesn't seem to be supported at the moment. The most convenient way to support it would be giving it as an option like you do with scope and state params.

ktuukkan avatar Jun 14 '18 06:06 ktuukkan

A workaround here is to directly pass any custom params into the authorization URL. These will be merged into the authorization URL this package generates:

https://github.com/jaredhanson/passport-oauth2/blob/a02839afb8d15f7d283ae09167973e4d22e8faf8/lib/strategy.js#L229-L230

oleg-codaio avatar Jul 24 '18 19:07 oleg-codaio

In a case you even cannot pass data as @soichih sugests, you can access the request object using this ugly nasty never-use-that way:

passportOAuth.Strategy.prototype.authorizationParams = function() {
    const req = passportOAuth.Strategy.prototype.authorizationParams.caller.arguments[0];
    // do whatever you need
}

I will create a pull request to avoid this ugly hack, hope it will be merged soon.

mdorda avatar Sep 26 '19 10:09 mdorda