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:
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.
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.
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.
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).
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.
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.
User authenticates via using Facebook.
Facebook generates a token for client.
Client sends a request to your backend application with this access token, email adress and authentication type/client id(Lets say 'facebook')
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With