Fay
Fay

Reputation: 173

NodeJS+Express: Passport vs OAuth2 in relation to scope (access permissions)

Imagine I'm implementing an API service at api.example.com that needs to protect its endpoints using OAuth2 with sufficient granularity to accommodate different user types.

This means we have the following roles:

Questions:

Q1 How should the application flow be implemented?

My thoughts are ...

A webapp must store the accessToken to api.example.com in a session, and send the sessionid to the web browser. If there is no accessToken, it must redirect the browser to auth.example.com/login/selectprovider/, providing the client_id="www.example.com" and client_secret, and redirect_url="https://www.example.com/".

On https://auth.example.com/login/selectprovider/ the user selects facebook or twitter or local, and auth.example.com redirects the user (again) to /login or facebook or twitter, using the client_id and client_secret and redirect_url=https://auth.example.com/twitter or https://auth.example.com/twitter to easily distinguish the three.

Facebook/twitter/local methods will authenticate the user and redirect the browser back to auth.example.com.

auth.example.com will then generate a (Bearer) accessToken for api.example.com and store it together with the user.id into a local database table, with associated scope ("facebook", "twitter" or "local"), put the key (userId) in the browser session and redirect to https://www.example.com/

Now when the user clicks on a link in the WebApp, www.example.com does a GET or POST on api.example.com, providing client_id="www.example.com" client_secret and access_token.

The api.example.com endpoints verify the accessToken, and if ok, execute the API and return the value to www.example.com that renders it to the browser of the user.

Q2 Is above the correct flow, or is there a better way? If correct, how does api.example.com validate the accessToken at its endpoints?

Should auth.example.com expose a special endpoint for this (eg. /userinfo) that can only be accessed with a client_id="api.example.com" and client_secret? That seems expensive to do for each call, but how else could api.example.com trust the validity of a token (because it expired or the user logged out)?

What's the OAuth2 standards compliant way?

Q3 In passport/OAuth2orize examples, I see 3 ways that authentication is validated:

Q4 What does passport.authenticate('facebook') do exactly?

This information is provided in the strategy.

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/facebook/callback"
  },
  function(accessToken, refreshToken, profile, cb) {
    User.findOrCreate({ facebookId: profile.id }, function (err, user) {
        return cb(err, user);
    });
  }
));

So this contains the client_id and client_secret. When is this used? Every time passport.authenticate('facebook') is called? Does do the whole redirect to facebook login page, get Authorization code grant and exchange it for an accessToken, store the accessToken internally somehow and keep it until a logout?

It seems unlikely but I don't see how it can actually authenticate the user without all this. And it would be too expensive to do for every API call, so I'm sure it works more efficiently. But I don't know how and studying the source code didn't make it more clear.

Q5 How does *api**.example.com know when the Bearer accessToken included by www.example.com in every API request is not forged or expired?

I assume it has to check it against the auth.example.com service, and that service in turn must check if the facebook/twitter session is still valid too, and refresh tokens using the refreshToken at that moment?

Upvotes: 0

Views: 828

Answers (0)

Related Questions