How to pass Auth token in header when we call Private API generate using OpenAPI after login? - access-token

I have used https://www.npmjs.com/package/#openapitools/openapi-generator-cli to generate API. I have used different services method for login, user detail and logout etc. When i have called login method and back-end return access_token and now I need to pass that TOKEN in header for other Private API call. Can you please suggest any solution for how to pass TOKEN in other private API call from client side?

Related

How to use Restcall with Spring Security

In my Spring MVC application I am using spring security. It works fine so far, but I have to admit, I do not understand all the details.
In the same application the user can call some controller functions by rest api. When the user (lets say Tom) does this, his authentication is lost. Instead the controller is called by user anonymous.
I tracked down that "user switch" to the code below. Variable restCall contains an url to my application. That call would work for user Tom, if he would place it in the browser directly. Using the restcall, the user changes to anyonymous.
1) Can I prevent that, when the calling User (Tom) was already logged in?
2) As those services should be called by a user that is not already browsing the web interface of the application, I would have to find a way to login by the rest call itself.
private void callWebservice(HttpServletRequest req, String restCall) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response
= restTemplate.getForEntity(restCall, String.class);
logger.debug(response.toString());
//assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
You need, for example, a JSON Web Token (JWT) Authentication.
Steps are the following:
1) Client does an authentication, a post request with username and password
2) If authentication is successful, server returns a token in which is coded the user
3) In your next call, GET or POST, you add JWT to your header, this way the server will know who you are, because server can decode the token, and can grant also the right authorities and functionalities

How to configure API to accept JWT token but validation should happen through Another API

In WEB API,
How to use [Authorize] attribute to make it work if validating token (JWT token) through another WEB API.
It works while I am using JWT Authentication within same API.

JWT + Laravel Socialite with OAuth Parameters

What I want to achieve:
Safely allow users to connect their accounts to different social medias using a Single Page Application.
What I am doing:
I am using an SPA and therefor utilizing JWT as my user authentication method. I am passing the JWT token in the OAuth call with Laravel Socialite like this:
return Socialite::driver($provider)
->with(['provider' => $provider, 'token' => $token])
->redirectUrl($redirectUri)
->stateless()
->redirect();
On the callback I get the user based on the token. Using this method allows the third party provider to get access to the JWT token. Which is very unsafe.
My Question(s):
Is there any better way to do this? Should I use some kind of hash + salt + secret?
You should check the JWT.
JSON Web Tokens are an open, industry standard RFC 7519 method for
representing claims securely between two parties.
JWT Token composes of three parts, header, payload and verify signature.
You are using stateless authentication and the only way to authenticate the user is by the JWT Token. To authenticate the user after redirect, you should create a payload containing application's user id, and pass to the third party provider, so that when redirect, they will pass the JWT token back to you.
It is no problem to pass the JWT Token to third party provider, but be aware that the payload should not contain any sensitive data. If the payload is somehow sniffed, it will not have any harm because, if hacker is trying to change the payload, the verify signature helps and the application cannot verify the token and the application will throw exception.
The signature is used to verify that the sender of the JWT is who it
says it is and to ensure that the message wasn't changed along the
way.

Return JWT token to javascript SPA from oauth login

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.

User registration for API/SPA

I am creating an API and a separate front-end app that will consume said API. In my particular case I'm using Laravel Passport for my API and some VueJS for my frontend app.
In order for a user to create an account, a user must POST to a route (/oauth/token) on the API which, requires a client_secret to be passed (https://laravel.com/docs/5.3/passport#password-grant-tokens).
The only options I see are:
Having the client_secret sent as a header from my frontend app. However, putting this token out in the open doesn't seem smart.
Don't require the client_secret at all. This doesn't seem much better than option 1.
Have a dynamic page on my frontend app that can securely store the client_secret and then send it to the API. While this is obviously the most secure, it seems to partially defeat the purpose of a fully static frontend (SPA).
What's the best practice for this type of approach? I've searched for how this is dealt with in general with an API and SPA, but I haven't found anything that points me in the right direction.
From my point of view, the Laravel Passport component seems to implement the OAuth2 Framework Protocol incorrectly.
The client_id and client_secret parameters are not part of the grant type.
For the Resource Owner Password Credentials grant type, the required parameters are username and password (see RFC6749 section 4.3.2).
client_id and client_secret are used to authenticate a confidential client that sends its credentials through the body parameters (see RFC6749 section 2.3.1). The Laravel Passport component should allow other client authentication schemes (especially the HTTP Basic Authentication Scheme). The RFC6749 also indicates that
Including the client credentials in the request-body using the two
parameters is NOT RECOMMENDED and SHOULD be limited to clients unable
to directly utilize the HTTP Basic authentication scheme
The OpenID Connect Core specification lists some of those schemes in its section 9. The RFC6749 does not indicates how public clients (e.g. SPA) should authenticate against the token endpoint. They are supposed to use the Implicit grant type which does not require a client authentication.
Anyway, a solution could be to use a kind of proxy. This proxy has to be installed on a server. It will receive all requests from the SPA (without client secret), add the client secret and transmit the modified request to the Laravel Passport endpoint. Then the response is sent to the SPA. This way the SPA never exposes the client secret.
I came across the same problem, and I didn't find much more documentation on the problem.
So here is what I did, that seems working great so far, you'll tell me if you see anything wrong.
For my apps, I'll be using password grant clients that I create on the fly for each "client" of my app. By client I mean browser, or mobile app, or anything.
Each browser, checks at startup if they have any client_id and client_secret into localStorage (or cookies, or anything). Then, if they don't, they call an endpoint of your API that will create a password grant client and return the information to the browser.
The browser will then be able to login the user using this new client information and his credentials.
Here is the controller I use to create a password grant client:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Http\Request;
use Laravel\Passport\ClientRepository;
class AuthController extends Controller
{
protected $hasher;
protected $clients;
public function __construct (Hasher $hasher, ClientRepository $clients)
{
$this->hasher = $hasher;
$this->clients = $clients;
}
public function makeClient (Request $request)
{
$client = $this->clients->create(null,$request->header('User-Agent','Unknown Device'), '', false, true);
return $client->makeVisible('secret');
}
}
As you can see, as the name for the client, I try to store the User-Agent of the browser. So I can potentially display a page to my user with all his clients and giving him the right to revoke some clients like:
"Google Chrome, New York". You can also store the client IP or anything in there that will help you identify more precisely the client type of device...
The simpler way would be to take care of the user registration with the Laravel app running Passport itself (and not with the frontend Vuejs app via API).
Once the user is registered and logged in, you can use Passport's CreateFreshApiToken middleware to add a token to the user's cookie while loading up your frontend app. No more problem with client_secret.
See https://laravel.com/docs/5.3/passport#consuming-your-api-with-javascript and https://mattstauffer.co/blog/introducing-laravel-passport#super-powered-access-to-the-api-for-frontend-views
Also oauth/token doesn't create a user I believe? It is supposed to deliver a token (for password grant client) or an authorization code (authorization code grant client).

Resources