Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I persist a session using OAuth 2.0 after authorization through a third party service? [closed]

I'm implementing an OAuth 2 based authorization model for an application I'm developing. I'm offering end-users the ability to login with Facebook or by setting up an email/password account with my API. The email/password authentication is straightforward using a password grant. I'm looking for help with the Facebook login flow.

My application is a single-page application that consumes a JSON API (my "resource server"). I'm using the Facebook JavaScript SDK to authorize the web app to access the end-user's email address.

When a user attempts to login with Facebook, the entire process takes place between Facebook and the web application. As a result, my API can't trust the Facebook authorization token until it verifies the token with Facebook's OAuth server.

As of right now I'm passing the Facebook accessToken to my API, which then verifies the user's authorization with Facebook via a server-to-server call of the "me" graph API. Here's an illustration of my current setup:

My current OAuth flow

So, at this point, I have a Facebook access token and an email address. I need to persist my session between my API server and the web application. What is the standard method of persisting the session at this point?

From reading the OAuth documentation, it seems that this is the type of situation that calls for an "implicit grant" between my API server and the web application, but that grant type is not available in the OAuth package I'm using. Also the author of the package says implicit grants are "very insecure".

My other thought is that I can create a random client ID and client secret, then pass them back to the web app so it can request an access token via a credentials grant. This seems illogical to me. Why wouldn't I just create an access token and send it back to the client to use directly?

I should be maintaining authentication directly between my web app and API server after the initial authorization from Facebook, is that correct?

I realize I could just generate a random password and send the user an HTTP Basic token, but I'd prefer to use OAuth unless there are no benefits.

like image 648
Ben Harold Avatar asked Jan 11 '16 23:01

Ben Harold


People also ask

How do Microservices communicate with oauth2?

Focusing, how to achieve oauth2 full flavor into microservices architecture. User can't access API without token. The token will be available when user given basic and authentication details to generate token for access API. All requests will consider one entry point API-Gateway but, service-to-service can communicate.

What is 3rd party OAuth?

OAuth and OAuth 2.0 are widely used authentication protocols which alert resource providers (e.g. Facebook, Twitter, Google, Microsoft etc.) every time resource owners give permission to third parties to run HTTP applications without exposing user passwords.

Does OAuth use session?

OAuth is the system that lets countries trade with each other, whereas session management is the system that enables trade within a country. You always require local trade – regardless of whether you exchange goods (data) with other countries or not (see “OAuth depends on Session management” section).

What happens during an oauth2 authentication flow?

OAuth 2.0 Access Tokens and Authorization Code The OAuth 2 Authorization server may not directly return an Access Token after the Resource Owner has authorized access. Instead, and for better security, an Authorization Code may be returned, which is then exchanged for an Access Token.


2 Answers

You can code your own custom grant class and authentication provider in your oauth implementation if you can.

Define a new client id for this kind of authentications.

  1. User authenticates via using Facebook.

  2. Facebook generates a token for client.

  3. Client sends a request to your backend application with this access token, email adress and authentication type/client id(Lets say 'facebook')

  4. Your custom grant decides which kind of token will be used. You can control client id/authentication type(above).
  5. If auth type is 'facebook', you will ask that access token to session store if it is not here you will ask to Facebook api and then if it is ok, save it in your session store(database, redis whatever else). We put in a session store to not ask fb everytime.(it is so basical concept)
  6. Then oauth will return token with your configuration.
  7. Your client will send the token for next requests with client id/authentication type. credentials will be facebook token and email will be username.

Custom grant decides token type(Spring security-oauth implementation)

    String clientId = tokenRequest.getClientId();
    ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
    Map<String, String> parameters = tokenRequest.getRequestParameters();
    String username = parameters.get("username"); //username is email
    String password = parameters.get("password"); //password is fb access token
    Authentication authentication = null;
    if ("facebook".equals(clientId)) {
        authentication = new FacebookAuthenticationToken(username, password);
    } else {
        authentication = new UserAuthenticationToken(username, password);
    }
    authentication = authenticationManager.authenticate(authentication);

Authentication Provider checks facebook token and validate it.

public class FacebookAuthenticationProvider implements AuthenticationProvider {

@Autowired
private FacebookApi facebookApi;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();
    // you can check your facebook session store
    boolean valid = facebookApi.isValidToken(username, password);

    if (!valid) {
        throw new BadCredentialsException("Username not found.");
    }

    Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

    return new FacebookAuthenticationToken(user, password, authorities);
}

@Override
public boolean supports(Class<?> authentication) {
    return FacebookAuthenticationToken.class.isAssignableFrom(authentication);
}
}

I put codes to be sample.

I usually force the users to set a password for my internal app after first facebook login (getting their email). Then everything is going much more simple. You can figure out what i mean.

like image 76
Sedat Yıldız Avatar answered Nov 03 '22 22:11

Sedat Yıldız


We are doing exactly what you are talking about on DynamicApis.com.

Here is what we are doing:

1) Prompt a user to log in. In our case we author oAuth2 access tokens ourselves OR we can proxy you through to facebook, github, etc... But at the end of the day the oAuth2 token that drives the session for DynamicApis is owned by us. But the rest of the workflow would be the exact same if it were authored entirely by a 3rd party like GitHub.

2) User logs in with email/passowrd.

3) User is redirected to DynamicApis.com with the authorization code

4) DynamicApis.com exchanges authorization code for access token (server to server call). At this point I have just explained oAuth2 flow

5) At this point we (let's say encrypt) the access token that was returned and issued on behalf of that user and use that as the KEY to a session provider (let's say Sql Server based). This session provider is owned by DynamicApis.com.

6) Now your session provider works exactly as it normally would. You have a key that represents a logged in user (hashed/encrypted access token) and multiple key/values associated to that key.

  • Your session provider will persist the session state (key value pairs) of data that you want to store on behalf of the user in the database or whatever you use

  • The session provider should have an expiration date equal to the expiration date of the access token (or a date less than the access token).

  • When the user logs out the session is destroyed.

  • The session key should exist in encrypted form in a cookie, url, or hidden on the page (just as session keys are persisted today)

7) Poof. You have a session for a logged in user.

You can actually reuse much of the built in ASP.NET session provider logic if you want to. Or you can build your own home grown system like we have at DynamicApis.com.

like image 32
Jerrod Horton Avatar answered Nov 03 '22 20:11

Jerrod Horton