lucj / sails-oauth2-api

140 stars 34 forks source link

Trusted apps skip auth dialog #9

Closed ChrisTerBeke closed 1 year ago

ChrisTerBeke commented 9 years ago

I made a nice middleware setup that lets you skip the auth dialog for trusted apps:

in config/oauth2.js

/***** OAuth authorise endPoints *****/
app.get('/oauth/authorize',
    isValidJwtTokenPolicy, // my custom jwt token login method, feel free to use any method that results in a correct req.user
    server.authorize(function (clientId, redirectURI, next) {
        Client.findOne({ clientId: clientId }, function (err, client) {
            if (err) return next(err);
            if (!client) return next(null, false);
            if (client.redirectURI !== redirectURI) return next(null, false);
            return next(null, client, client.redirectURI);
        });
    }),
    isTrustedClientPolicy,
    function (req, res, next) {

        // if trusted via isTrustedClientPolicy, skip ahead to next, which is the server.decision() function that normally is called when you post the auth dialog form
        if (req.trusted) {
            return next()
        }

        return res.render('dialog', {
            transactionID: req.oauth2.transactionID,
            user: req.user,
            client: req.oauth2.client,
            jwtToken: req.query.token
        });
    },
    server.decision(),
    server.errorHandler()
);

api/policies/isTrustedClient.js

module.exports = function(req, res, next) {
    var clientId = req.query.client_id;

    if (!clientId) {
        return res.send(400, "Missing client_id parameter");
    }

    Client.findOne({
        clientId: clientId
    }).exec(function (err, client) {
        if (err) return res.send(500, err.message);
        if (!client) return res.send(400, "Client not found");
        if (client.trusted) {
                        // add needed params to simulate auth dialog being posted
            req.trusted = true;
            req.body = req.query;
            req.body.transaction_id = req.oauth2.transactionID;
            return next();
        }
        return next();
    });
}

Now, you can do a GET to /oauth/authorize, and if your application is trusted, you'll be redirected to the redirectURI immediately!

Make something nice with it :)

lucj commented 9 years ago

Hello, Thanks a lot, that is great. Could you make a pull request ? Luc

Le 16 oct. 2015 à 00:37, ChrisTerBeke notifications@github.com a écrit :

I made a nice middleware setup that lets you skip the auth dialog for trusted apps:

in config/oauth2.js

/* OAuth authorise endPoints */ app.get('/oauth/authorize', isValidJwtTokenPolicy, // my custom jwt token login method, feel free to use any method that results in a correct req.user server.authorize(function (clientId, redirectURI, next) { Client.findOne({ clientId: clientId }, function (err, client) { if (err) return next(err); if (!client) return next(null, false); if (client.redirectURI !== redirectURI) return next(null, false); return next(null, client, client.redirectURI); }); }), isTrustedClientPolicy, function (req, res, next) {

    // if trusted via isTrustedClientPolicy, skip ahead to next, which is the server.decision() function that normally is called when you post the auth dialog form
    if (req.trusted) {
        return next()
    }

    return res.render('dialog', {
        transactionID: req.oauth2.transactionID,
        user: req.user,
        client: req.oauth2.client,
        jwtToken: req.query.token
    });
},
server.decision(),
server.errorHandler()

); api/policies/isTrustedClient.js

module.exports = function(req, res, next) { var clientId = req.query.client_id;

if (!clientId) {
    return res.send(400, "Missing client_id parameter");
}

Client.findOne({
    clientId: clientId
}).exec(function (err, client) {
    if (err) return res.send(500, err.message);
    if (!client) return res.send(400, "Client not found");
    if (client.trusted) {
                    // add needed params to simulate auth dialog being posted
        req.trusted = true;
        req.body = req.query;
        req.body.transaction_id = req.oauth2.transactionID;
        return next();
    }
    return next();
});

} Now, you can do a GET to /oauth/authorize, and if your application is trusted, you'll be redirected to the redirectURI immediately!

Make something nice with it :)

— Reply to this email directly or view it on GitHub.

ChrisTerBeke commented 9 years ago

Sure! I assume you want the policy in the repo as well as some examples?

lucj commented 9 years ago

That would be great ;) Thanks a lot

On Tue, Oct 20, 2015 at 10:37 AM, ChrisTerBeke notifications@github.com wrote:

Sure! I assume you want the policy in the repo as well as some examples?

— Reply to this email directly or view it on GitHub https://github.com/lucj/sails-oauth2-api/issues/9#issuecomment-149478100 .

Luc Juggery - https://about.me/lucjuggery

davoscript commented 8 years ago

@ChrisTerBeke thanks for such a useful piece of code!

I'm trying to figure out if it is possible to do an ajax GET request to the authorize endpoint (which I'm already doing), then skip the authorization dialog (which you already did) and then return the token in a JSON instead of doing a redirection.

Any clues? Help is much appreciated. Thanks in advance.

ChrisTerBeke commented 8 years ago

@davoscript I think you'd have to change the next() middleware that makes the decision and then does the redirect in the package itself. However that would mean your app does not comply anymore with OAuth specifications. Instead you could just build a simple JWT token auth that returns an access token.

Edit: Sails doesn't seem in active development anymore, so we're switching away from it, something to keep in mind ;)

davoscript commented 8 years ago

Thanks for your quick response @ChrisTerBeke, I was actually thinking to use another flow, maybe "Resource owner password" is more suitable for my needs or as you mention JWT (which I'm not familiar with, but will take a look).

I'm trying to build OAuth to work with my single page app and future mobile apps.

davoscript commented 8 years ago

Hey guys, just commenting that I used @ChrisTerBeke approach to achieve the auto-authorization skip but without modifying the isTrustedClientPolicy.js since it was also validating the grant_type parameter.

Here's my code in case someone finds it useful:

// OAuth authorize endPoints
            app.get('/oauth/authorize',
                login.ensureLoggedIn(),
                server.authorize(function(clientId, redirectURI, done) {
                    Client.findOne({clientId: clientId}, function(err, client) {
                        if (err) { return done(err); }
                        if (!client) { return done(null, false); }
                        if (client.redirectURI != redirectURI) { return done(null, false); }
                        return done(null, client, client.redirectURI);
                    });

                }),
                function(req, res, next){

                    // TRUSTED CLIENT
                    // if client is trusted, skip ahead to next,
                    // which is the server.decision() function
                    // that normally is called when you post the auth dialog form
                    if (req.oauth2.client.trusted) {

                        // add needed params to simulate auth dialog being posted
                        req.trusted = true;
                        req.body = req.query;
                        req.body.transaction_id = req.oauth2.transactionID;
                        return next();

                    }

                    return res.render('auth/dialog', {
                        transactionID: req.oauth2.transactionID,
                        user: req.user,
                        client: req.oauth2.client,
                        jwtToken: req.query.token
                    });

                },
                // We added this 2 methods here in case the form is skipped (TRUSTED CLIENT)
                server.decision(),
                server.errorHandler()
            );
lucj commented 8 years ago

would you mind creating a PR ? :)