Return JWT token to javascript SPA from oauth login - laravel

I'm developing a javascript spa in vue.js which is going to eventually be a cordova application. As well as a backend api built with lumen.
I'm trying to provide login with facebook and google functionality. I've added the laravel socialite package and created a redirect and callback route. Ive created a page in my spa with the login buttons that direct to my api redirect. The user is redirected to facebook's oauth mechanism I login, the callback routes handle function looks something like this
public function handleProviderCallback($provider)
{
$oauthUser = $this->socialiteManager->with($provider)->stateless()->user();
$userEntity = $this->repository->findOrCreateOauthUser($oauthUser);
$providerEntity = app()
->make('em')
->getRepository('Entities\Social\Provider')
->findOneBy(['name' => $provider]);
if(is_null($providerEntity))
{
throw new \Exception('Oauth Provider not found');
}
$socialAccountEntity = app()
->make('em')
->getRepository('Entities\Social\SocialAccount')
->findOrCreateSocialAccount($providerEntity, $oauthUser, $userEntity);
$token = $this->auth->fromUser($userEntity);
$resource = $this->item($token)
->transformWith($this->transformer)
->serializeWith(new ArraySerialization())
->toArray();
return $this->showResponse($resource);
}
It basically gets a the oauth user, finds or stores them in the database, finds or stores their social account info,
$token = $this->auth->fromUser($userEntity);
Then authenticates them with JWT issuing a token. Which is then serialised and returned as a json response.
The problem is that the response is given while on the backend application, im never returned back to the javascript SPA.
Instead of returning json I could do some redirect like
return redirect()->to('/some-spa-callback-route');
But should the api be aware of the SPA location? and how will this work when the SPA is ported into cordova, as the mobile application wont have a url?
My thoughts are that A
The social provider should redirect directly to the SPA at which point it should make another request exchanging the authorisation code for a JWT token.
B it redirects to the SPA with a query string containing the token, which doesn't sound secure.
or c sends some type of cookie back.
And I am still confused as to how to actually redirect from my api to a mobile application.

In the end I ended up with the following login flow
User is directed to Oauth provider
Oauth provider returns an access token to the client
the client sends the access token to my api
my api sends a renew request to the Oauth provider
the Oauth provider validates the token and returns a new one to my api
my api exchanges the access token for a jwt token
my api returns the jwt token to the client
In my opinion it is the only correct way to authenticate SPA applications, and it is important to renew the Oauth token the client provides rather than blindly exchanging for a jwt as you can't trust the client, and is better than issuing redirects from the api that isn't very restfull

Instead of dealing with 2 services, your spa should talk to a single auth service in your backend. You register your service as the oauth callback and you handle oauth/jwt as you described. Your auth service can also be the decision point for user (re-)authentication. Since your frontend calls your backend directly, you can now return the json payload back to your web/mobile caller.

Related

Laravel socialite login and register by REST - best flow?

I'm doing some Android app that needs API and users.
I'm planning adding login (and register) button via Facebook.
I'm wondering: how should the flow of such an operation look like?
My idea:
Request the Facebook token in the app.
Send the token to the laravel backend by POST request (is this even secure approach?)
Get the Facebook user by Facebook token using socialite
Create / auth laravel user using Facebook user.
Return laravel's bearer token to the app (do I need passport to get the token or laravel has something built in?)
Is this the best approach?

Facebook and JWT Auth w/ Laravel back-end and React Native app

I have built a website with vuejs front-end and laravel back-end.
Only way to login is via Facebook Login using Socialite
All that works fine.
Now I am building some React Native apps (Ios/Android) that also use Facebook login but need to interact with the same web api.
I want to use JWT to secure the API for React Native -> Laravel API
I set up JWT w/ Dingo on Laravel side and I am able to generate a token using the JWTAuth::fromUser(). And I have established some API endpoints that use the token to authenticate.. so far so good.
Now here's the part that becomes sticky. I understand that on the Laravel side of things you can create JWT token with any user.. right now the JWT "identifier" is simply "id".. and it's my understanding that the token I generate from JWTAuth::fromUser() simply has no idea or care that this user doesn't have conventional credentials and instead used a Facebook Login.
On the React Native side however.. when a new user first authenticates via the Facebook Login.. it has no idea what the "matching user" is on the Laravel app, all I have to go on is basically the unique Facebook Provider Id.
So the question is as follows:
How can I generate a JWT token on the React Native side using only the Facebook Provider Id and the JWT Secret, and more importantly, how do I modify my JWT code on the Laravel side so that it can understand tokens that were generated with the Facebook Provider Id and JWT Token
In other words, I think my Laravel JWT implementation needs to be modified so that tokens are created/parsed purely on the basis of the Facebook Provider Id because otherwise it won't match up with tokens generated on the React Native side.
Many thanks!!
Ok after doing some reading I think this flow might work. Your thoughts please?
1 User authenticates via Facebook on in on Android/Ios app
2 Retrieve facebook access token
3 Do api call to public endpoint on web server and pass FB Access Token and FB ID
4a Web server makes Facebook Graph Api call w/ Access Token and verifies token is valid, is authenticated with Facebook App, and matches Facebook ID
4b If user doesn't exist on web first.. create user
5 If above matches, then web servers generates JWT token from user model and returns JWT token to app
6 App now uses JWT token for future API calls

In spring social for Facebook api, why does facebook.isAuthorized always return true?

I have an angular2 app that has a Facebook login feature. When the user authenticates themself, I then send this accessToken to the server.
The server program is with Springboot and I make use of spring social.
I want to check to see if this user is authorized. So I call:
facebook.getToken() returns the access token generated on the client side. When I call facebook.isAuthorized() it returns true...As expected, because I am sending real data.
Although if I send bogus data such as:
(The token in this case is fabricated by me) to the same API endpoint
facebook.isAuthorized returns true. This is unexpected because in this case I am fabricating an accessToken.
The spring-social dependency is this:
Why does isAuthorize return true for a real access token, as well as a fake one? How can I check to see if a user of my angular2 app has authenticated themselves through Facebook on the server side?
Implementation of isAuthorized() for FacebookTemplate can be found at https://github.com/spring-projects/spring-social/blob/a6bf2626ee8ac81765c416029ca033affc94fc6c/spring-social-core/src/main/java/org/springframework/social/oauth2/AbstractOAuth2ApiBinding.java#L87.
With this source its quite obvious that isAuthorized() only checks if there is any access token provided.
To validate your token you can run any request which need authorization (e.g. userOperations().getUserPermissions()) and check for InvalidAuthorizationException or you can find some inspirations in how to verify facebook access token?.

Issue token to logged in user via spring

I have a Spring (3.2) based web app that a user can log into. The site will also provide an API secured via OAuth 2.0. My question then, is how do I go about generating a token for a logged in user?
The underlying idea here is that there will be a mobile app that opens up a web frame to the login page, which will eventually redirect to a url schema with an oauth token that the app will catch and then use for the api calls. Looking at the code for TokenEndpoint, I see that it defers token creation to a list of TokenGranter types. Should I be creating my own TokenGranter extended class, or am I looking at this all wrong?
I ended up writing a controller like this:
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation(csOauthAuthorizeUrl)
.setClientId(csClientId)
.setRedirectURI(
UrlLocator.getBaseUrlBuilder().addSubpath(AUTH_CODE_HANDLER_URL).asUnEscapedString())
.setResponseType("code")
.buildQueryMessage();
UrlUtils.temporarilyRedirect(httpResponse, request.getLocationUri());
return null;
Then handling the code returned. My big problem here was that I had the /oauth/authorize endpoint set to use client credentials. Once I realized that tokens were being issued for the client ID instead of the user, it started to make sense.
So you want to use the Authorization Flow of OAuth. Spring has already support that, if you have configured the spring-security-oauth correctly, you just have to redirect the user/your mobile apps to /oauth/authorize?client_id=xxx&response_type=code this will redirect user to authorization page, if user has not login yet, it will redirect the user to login page then to the authorization page.
After the user completed the authorization process, it will redirect the user to an already registered redirect_url parameter with the authorization_code 'yourapp.com/callback?code=xxxx'.
Your application should exchange this authorization_code with the real token access to /oauth/token?grant_type=authorization_code&code=xxxx&client_id=xxxx&client_secret=xxxx
After that you will receive the token access that can be used to access the resource server.

Understanding the VS2013 MVC5 SPA Template WebAPI Security Features

I am trying to understand the security features of the VS2013 MVC5 SPA Template WebAPI.
In Startup.Auth.cs there is this -
TokenEndpointPath = new PathString("/Token")
and this -
AuthorizeEndpointPath = new PathString("/Account/Authorize")
In my understanding, the AuthorizeEndPointPath is for when your acting as a 3rd Party OAuth authorization server.
However how it is used in the template, the flow seems to be
Login via Forms Authentication
Redirect to a secure page
Javascript checks for a bearer token in the local storage, it doesn't exist, so it redirects to this Authorize endpoint.
window.location = "/Account/Authorize?client_id=web&response_type=token&state=" + encodeURIComponent(window.location.hash);
Logs into app with OAuth security, returns token, which will be passed on subsequent API requests.
The /Token endpoint never seems to be used. A prior version of this templated did an ajax post to /Token to login. I have a similar situation where the website is secured via Forms authentication/cookies but the WebApi is secured by Bearer token.
Is the Authorize endpoint being used correctly in this SPA template - is this the correct pattern to follow? It seems like the appropriate way to authenticate for bearer token security "internally" for the app would be a "client credentials grant" though not sure how to generate the "secret".

Resources