How to save a session using OAuth 2.0 after authorization through a third-party service?

I am using the OAuth 2-based authorization model for the application I am developing. I offer end users the ability to log in using Facebook or by setting up an email / password account using my API. Email / password authentication is simple using a password. I am looking for help in the Facebook login stream.

My application is a one-page application that uses the JSON API (my "resource server"). I use the JavaScript JavaScript SDK to authorize a web application to access the email address of the end user.

When a user tries to log into Facebook, the whole process takes place between Facebook and the web application. As a result, my API cannot trust the Facebook authorization token until it validates the token with the Facebook OAuth server.

I am currently passing Facebook the accessToken to my API, which then verifies the user’s authorization using Facebook via a server call to the me server API. Here is an illustration of my current setup:

My current OAuth stream

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

From reading the OAuth documentation, it seems like this is a type of situation requiring an “implicit grant” between my API server and the web application, but this type of grant is not available in the OAuth package that I use . The author of the package also says that implicit grants are "very insecure . "

My other thought is that I can create a random client identifier and client secret, and then transfer them back to the web application so that it can request an access token through a credential grant. It seems illogical to me. Why don't I just create an access token and send it directly to the client?

I have to support authentication directly between my web application and the API server after the initial authorization from Facebook, right?

I understand that I can just create a random password and send the user a basic HTTP token, but I would prefer to use OAuth if there are no benefits.

+5
source share
2 answers

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

Here is what we do:

1) Ask the user to log in. In our case, we ourselves authorize the OAuth2 access tokens, or we can proxy you via facebook, github, etc. But at the end of the day, the oAuth2 token that controls the session for DynamicApis belongs to us. But the rest of the workflow would be the same if it were completely created by a third party such as GitHub.

2) User logs in via email / passowrd.

3) The user is redirected to DynamicApis.com with an authorization code

4) DynamicApis.com exchanges an authorization code for an access token (server to server call). At this point, I just explained the oAuth2 stream

5) At this point, we (suppose we encrypt) the access token that was returned and issued on behalf of this user, and use it as the KEY for the session provider (suppose that it is on the Sql Server). This session provider is owned by DynamicApis.com.

6) Now your session provider works exactly as usual. You have a key that represents a registered user (a hashed / encrypted access token) and several keys / values ​​associated with this key.

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

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

  • When the user logs out, the session is destroyed.

  • The session key must exist in encrypted form in the cookie, url or hidden on the page (just like the session keys are stored today)

7) Poof. You have a session for a registered user.

In fact, you can reuse most of the ASP.NET session provider built-in logic if you want. Or you can create your own home-developed system, like ours on DynamicApis.com.

0
source

You can program your own privilege class and authentication provider in your oauth implementation if you can.

Define a new client identifier for this kind of authentication.

  • The user authenticates with Facebook.

  • Facebook generates a token for the client.

  • The client sends a request to your server application with this access token, email address and authentication type / client id (allows you to say "facebook")

  • Your user grant decides what type of token will be used. You can manage the id / authentication type client (above).
  • If the auth type is 'facebook', you will request an access token in the session store, if it is not here it will ask for the Facebook api, and then, if everything is ok, save it in your session store (database, redis everything else). We put in the session store so you don’t ask fb every time (this is such a fundamental concept)
  • Then oauth will return the token with your configuration.
  • Your client will send a token for the following requests with the client identifier / identifier. the credentials will be the facebook token, and the email address will be the username.

User grant decides token type (Spring security-oauth)

  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); 

The authentication provider verifies the token and verifies 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 the codes in the sample.

I usually force users to set a password for my internal application after the first login to facebook (receiving email). Then everything will be much simpler. You can understand what I mean.

+1
source

Source: https://habr.com/ru/post/1240388/


All Articles