Moving from Session-based token mechanism to OAuth 2.0 mechanism - javascript

I own a Play Framework application acting acting as a backend server providing a set of REST APIs.
At client side, I own an AngularJS application that calls APIs from backend-server through AJAX.
Currently, I make use of a solution based on Session-token mechanism.
Meaning that each time a user logs in successfully, a cookie is retrieved at client side containing an authentication token.
At each request then, the cookie value (the auth token) providing by the client request is extracted on the server and if valid, the request is made.
Now I want to use OAuth 2.0. Reasons are? :
It's a great standard way to secure API, avoiding the use of a datastore (Memcached) to keep auth tokens at server side, as I'm currently providing.
I want to provide a better secure than a sole cookie, by providing some client_secret and nonces to avoid some replay attacks etc...
I want to restrict the amount of clients capable to call even public REST API I provide, meaning API that allows anonymous call, like listing a list of items for instance.
The point is that I don't involve a third party, since all protected resources are on my own.
I came across this article explaining how to secure internal REST API with OAuth 2.0 implementing a 2-legged instead of a 3-legged as usual.
However, I can't figure out how the Client Credentials flow could authenticate a specific user, when calling for a REST API that needs to have a user authenticated.
Indeed, Client Credentials flow seems to be based on a global client_id, client_secret keys (global to the app, so in my case to my Javascript app), and therefore not enough specific to target a specific user and controller its specific rights.
Any help would be great.

Seems like you should use "Resource Owner Password Credentials Grant" (https://www.rfc-editor.org/rfc/rfc6749#section-4.3). It is dead simple - put client ID/secret in Authorization header and put user name/password in query variables. Here is an example from the RFC:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
Server side you can check for both validity of the client (your javascript app) as well as the user. Just remember that it is impossible to protect the client credentials as it will be embedded in your (downloadable) JavaScript code. The user name/password is entered directly by the end user.

Related

OAuth2 flow in web frontend and REST API

I'm working on a project based on Phalcon which consists in two different stand-alone subprojects: a php + angular frontend and a php REST API.
I protected the API with OAuth2, using PhpLeague OAuth2 Server. The API server is the OAuth2's authorization server AND resource server.
This is the actual flow:
The user can browse the public endpoints of the frontend, and when hits a private page, gets redirected to the login page;
The login page has username and password, POSTs them to the frontend server;
The frontend server calls a public method on the API server, which is expecting a Password Credential Grant: it validates the credentials and sends back an access token and a refresh token;
The frontend server caches both the access and refresh token in session and uses it for some API calls: the first of those is the '/users/me', which gets info about the current user and its ACL on the frontend sections;
The frontend server sends the page to the browser, which loads its javascript files.
Now, OAuth2 states that access tokens should be short-lived and refresh-token should be long-lived: in the frontend server logic, the API calls which receives a 401 (caused by the expired access token) are retried by sending first the refresh token to obtain a new access token via a Refresh Token Grant. If this second call is rejected, I assume the user is no more logged in (refresh token expired / revoked).
The pages are using Angular to perform data and ux/ui management. My question is:
should the Angular code call directly the API server?
Actually the first thing my javascript code does is to get a config object from the frontend server, which contains the access token too, and uses it to make the calls to the API server. The problem with this is that i should rewrite again the "refresh token logic" in javascript (after it expires, i get 401s), and by what I have read on the subject i understood that it is better to not make the refresh token visible to the client (as it can generate new access tokens).
So i was thinking about a "two step approach", where every javascript API call goes to an endpoint on the frontend server which relays it to the API server, but this is obviously slower (JS -> FRONTEND -> API and API -> FRONTEND -> JS).
What is the correct approach? It's not very clear to me if the frontend should be considered as two clients (php + js) which should work separately or not, as I imagine that an hypothetical iOS app would be making calls 100% against the API server.
I have used the same approach in my own projects. The problem that we have is that the client is not secure. In order to generate / refresh a token, you need to pass secure information to the authorization server.
I have done the same as you basically, let the back-end handle the tokens and their temporary storage. You cannot and should not trust the client with important information which lets you generate tokens. In terms of delays, I wouldn't worry about it too much since you're not going to be doing that much extra work, you won't even notice the delays. I have a system like this built and used by hundreds of thousands of users with absolutely no issues.
Now, you have said a few things in here which make me wonder what you are doing.
OAuth2 is not a user authentication system, it's an application authentication system. You don't pass a user and their password and generate a token for them, you pass a ClientID and ClientSecret and they generate a token for you. Then you have an endpoint which gives you the user details for this user, you pass your userid or username and get the details of that user.
A token expired does not mean your user is logged out. Those are two completely different things. How are you going to expire a token for example, when your user wants to log out? You can't, your token will still be valid until it expires after the set amount of time has passed.
A token can be used for let's say half an hour, but your user may use the website for 1 hour. So before you hit any API endpoint, you could check ... has this token expired yet? if yes then you can go and refresh it and keep working without having to bother your user with a new login screen.
The whole point of an OAuth2 system is to make sure that only authorised clients can access it. A client is not a user, it's an application. You can have a website for example and you only want users of that website to access your API.
You can have endpoints like ValidateUser for example, where you take a username and a password and return a yes or no and then you log your user in based on that.
Irrespective of language/framework, second approach is secure and better than first one because to get access token by providing refresh token to Authorization server, it still requires Client ID and Secret which should never be passed to Browser for security reasons.
In first approach, to make a direct call it will not work if your Authz Server is hosted on different domain than your frontend server because of Same Origin policy of browsers. Even if they are on same domain, still you are exposing Client ID and Secret which will compromise your frontend server

How to set up session token between JS and PHP API?

I have designed a simple HTML/CSS and JS/jQuery application, and now it's the moment of authentication integration. On the server side, I have done a REST API which allows clients to get some data. But, now I want to authenticate each request with access and/or session token.
I read many websites to find agreements or advice to establish security between the client (JS) and the REST API (PHP), but unfortunately I found nothing or not interesting.
So I ask you to enlighten me (if you want) to know what to do, what to implement, conventions, etc.
What I read:
Designing a Secure REST (Web) API without OAuth
Token Based Authentication for Single Page Apps (SPAs)
I cannot post more links according to my reputation...
Just give me advice, ways how to store private token (RSA) or access/session token for API.
Don't hesitate to give your reaction, and tell me if I'm not exact or something else.
You need to use a token-based authentication for your REST API. JWTs are the best in this particular case.
Why Use JSON Web Tokens?
Tokens are stateless. The token is self-contained and contains all the information it needs for authentication. This is great for scalability as it frees your server from having to store session state.
JWTs can be generated from anywhere. Token generation is decoupled from token verification allowing you the option to handle the signing of tokens on a separate server or even through a different company such us Auth0.
JWTs have fine-grained access control. Within the token payload you can easily specify user roles and permissions as well as resources that the user can access.
This will be your typical authentication flow process:
A user signs up/logs in, during the login process, you generate a JSON web token from the server and return it to the client. Since you are using PHP, you can use this library for the generation and signing of the token.
Store the JWT returned to the client on the browser Web Storage(local/session storage). It can also be stored in a cookie.
For subsequent HTTP requests from the client to the server, you send the token via headers/query, then the server validates the token. If it's valid, the user is authenticated otherwise the user is rejected.
BTW, if you don't want to implement authentication yourself, you can use Auth0, check out VanillaJS SPA and PHP quickstart
I hope this information helps. Cheers!
Authenticating REST API's with JavaScript front-ends is difficult because the JavaScript code is completely readable by anyone visiting the site so storing any kind of login credentials is no good.
With a standard Server to Server set-up simply using basic auth over HTTPS is more than enough but basic auth is no good for JavaScript SPA's as the credentials are in plain view.
For SPA's you need to be looking at JSON WebTokens, as your back end is in PHP you need to be looking at PHP-JWT from firebase. You can get the code here: https://github.com/firebase/php-jwt or recommended using composer:
composer require firebase/php-jwt
The package makes implementing JWT super simple see the docs for a complete code example. Also check out the JWT for a complete break down https://jwt.io/
I suppose Jwt (https://jwt.io/) is good solution for your question.
On the client side you can store the token on the localStorage or some global variable (for SPA).
You can transfer token on the HTTP header or as request parameter. It works.
Also you can see https://auth0.com/blog/angularjs-authentication-with-cookies-vs-token/

Proper OAuth2 flow for public first-party clients

I'm a regular reader here at stack overflow but this is my first question.
I'm developing an authorization-server using the OAuth2 specs. And I just got stuck with how do I ensure the first-party client authenticity while using the password flow. I read many forums and this is what I got:
Javascript single-page clients
This blog post by Alex Bilbie, he states that to avoid the client_secret problem we should just:
It’s simple; proxy all of your API calls via a thin server side component. This component (let’s just call it a proxy from here on)
will authenticate ajax requests from the user’s session. The access
and refresh tokens can be stored in an encrypted form in a cookie
which only the proxy can decrypt. The application client credentials
will also be hardcoded into the proxy so they’re not publicly
accessible either.
But now this proxy can be accessed by someone impersonating my
angular app. And then I came across this blog post from Andy
Fielder: How Secure is the OAuth2 Resourc Owner Password Flow
for Single Page Apps. He basically says to rely on CORS to
avoid impersonating JS clients.
It is a good idea to use both approaches to secure my JS app?
Native Apps (Desktop and Mobile)
In the case of mobile apps, I only found cases for Authorization
Code and Implicit flows. This is not what I want, as the redirects
will compromise the user experience. So my thoughts on this is:
I will use the ROP flow and then register the client with a
client_id generated for this particular installation and attach it
to the user account, receiving the access_token and a
client_secret as response. Any other token request made by this
client MUST carry this credentials (as the client_id is specific
for the installation, I will be able to check if this client is
already authenticated). This way if someone uses any credential for
impersonating a client, or even registers a bogus client, I can take
mesures to revoke the user and client access.
I know that this can be overthinking, and I also know that some of this matters doesn't avoid anything. I just feel that is my job to protect my API as much as I can.
I would really appreciate your thoughts about this matters! Am I really overthinking? Should I just use the concept of a 'public client' and carry on?
Thank you all and happy coding!
First of all, this problem is not a common priority because most applications are developed first with website, and after with the API. This is probably the reason because no one knows how to deal first clients with oauth2, because everyone have developed other ways to do that and oauth2 is needed only to grant user access to third party applications.
Even if you have develop the oauth2 authorization server only for your first clients applications (thinking about a single authentication mechanism instead of developing many), you should try to develop the authorization code or implicit grant types. You will realize that you need a way to check what user is actually logged in.
The two common methods are:
user session (based on Cookies)
user access from localStorage (based javascript)
In either ways you need to check your application security, user session is vulnerable to CSRF, localStorage are vulnerable to XSS. There are a lot of articles about how to secure your website against either, so I will not suggest anything here, you just need to know that they exist.
Now that you choose your authentication method we can start to do some consideration about:
Javascript single pages applications
Proxy
Having a proxy that filter all requests in my opinion is like to have a door with the keys always inserted. It's useless even build the door.
However, for session based authentication it's the only way to do it. Allowing session authentication on your Rest API will open to CSRF security issues, so you need to have a proxy layer that get the user session, retrieve the access token from the session and do the request to the Rest API adding the Authorization header.
CORS
With this method you need to store the user access token in the localStorage, because the token is retrieved from the Js client directly.
Using CORS you are sure that other websites cannot do requests to your Rest API from a browser. But your first client need to be public (ie: it does not have a client_secret).
Native Apps (Desktop and Mobile)
In my first application I tried to use the same mechanism that you suggest to secure the auth flow. However that type of mechanism require that you identify every user client in an unique way. This is not possible in iOS for privacy reasons and with some probability it will denied in the future releases of Android. So you should rely on a public client and add only the client_id in your native application code.
This means that your native app client/your js client can be impersonalized? Yes, and there is no way to prevent this with oAuth2 resource owner password credentials grant type.
The main reason about this is because oAuth2 is not for authentication, only for third-party authorization, and that grant type was added only for specific third-party applications trusted enought to use directly the user password. You could read more about this argument here and here.
At the end
You still need a way to auhorize your user, and I think that the best you can achieve using oAuth2 is what Auth0 did.
Essentially this Saas manage your users with an oAuth2 server + OpenID connect, so you are always managing your users like its a third-party application and everything works fine.
Indeed, you can see on this page that for mobile applications they suggest to use a browser based login form, because the native one can be impersonalized by everyone that decompile your application, but if you wrap it into an authorization code flow it works fine.

JavaScript REST Client and session management

I've been looking around for an answer to this question, but it looks like that nobody does this. Imagine you are designing a javascript REST client, and you want to create a login page. Surely, after the login you will be authenticated.
So the following requests to the REST API will depend on your current user id, which should be stored on the client side following the RESTful way.
My question is how to store this "session" information using Javascript. I've looked into cookies, but it seems to me too much plain text for one to trust. Also using cookies one could store there an session id that maps to the user information on the server, but this violates the Stateless concept from REST.
Which the best approach to solve this problem?
We are also building similar kind of architecture where RESTful API will be accessed by a javascript client.
We will authenticate client with client credentials and generate an authentication token and that will be sent to client. Client will store it in cookie or in local data store. Further requests to API from this client will be sent using HTTP authorization header and including that token in the header. We will authorize the request at API end for the given token and request will be served once it is authenticated.
Until n unless you don't access cookie information on server side I don't think this will violate stateless principle of REST as we are not maintaining any state of the client on server (we are but not binding it to any server). Regarding the authentication process using token, I don't think we are binding the server and client here, because we have multiple servers and using load balancer and still this request may be served by any server (similar to Google api).
Note: We are doing this using HTTPS protocol so we are sure that all this communication is secured.

Implementing 2-legged OAuth to get user specific data for use in Javascript

I am diving into OAuth 2.0 to protect my RESTful services. I own the consumer and the provider sides, and therefore do not need the end-user to allow access to the data on the provider. I've experimented with client credentials flow, but this appears to only allow me to get a token for my whole client, but not for an individual user. If I used the token for my client in Javascript, then it would be given to all users and wouldn't be very secure because users could potentially get data for all other users.
Is there a way that I can use 2-legged (aka client credentials) to get a user-specific token that can be used in Ajax/Javascript (similar to what the implicit flow provides, but without user approval)?
Thanks.
You're right, the standard says nothing about user credentials for the "client credentials grant" scenario. However, if the protected resources belong to users, each token should be related to a specific user. Based on your question, I think this is the case.
If you're implementing the OAuth server, too, then you can easily do this. Just add a "user_id" parameter to the authorization request in the "client credentials grant" scenario. Processing the request on the server side, you can tie the token to the specified user. You may consider this as your own slight extension to the protocol.
You may also want to be completely standard-comformant and do nothing that's not written in stone, or you may not have access to the OAuth server implementation. In this case, you may try to use user-agnostic tokens (or "whole client" tokens as you called them in your question). However, accessing the protected resource, you must explicitly specify the user (e.g. as part of the resource path or in a query parameeter using HTTP) since it cannot be deduced from the token itself.
I discovered the ability to auto-approve clients, so the user does not have to authorize when certain clients access their data. This works in my scenario because I am using the same single sign-on mechanism for both websites, and the login to the provider is transparent to the user.

Categories