I am looking to implement SSO in all my future php/angular applications. I see there are services (Auth0, oauth.io, etc) that are sort of the middle man of an SSO app and there are protocols such as OAuth 1.0/2.0 but in regards to creating a custom SSO solution (using aforementioned OAuth protocols, I assume), I am a little foggy on the complete flow of the process.
What I do get:
App gets Access Token
(optional) App validates Access Token
App (with Access Token) gets access to a particular API and returns result. For
example, Facebook profile information.
What I don't get:
What to do with that information once I have it. Do I retain the access token and request information from the API source each time they login? How do I relate my own application data to the API data? Would I create a different kind of user record that just contains the access token and application's userid?
Do I retain the access token and request information from the API source each time they login?
If the token does not expire, you can hold on to it in a data store and use it with each request. Many times, though, the token will expire, and you need to request a new one each time you start a session. In this case you'd probably store the token in memory instead of a permanent storage location.
How do I relate my own application data to the API data?
I think we'd need to know a little more about your application to answer this question.
Would I create a different kind of user record that just contains the access token and application's userid?
Again, we'd probably need a little more information about your application. If you were persisting the token (in the case that it doesn't expire), then you need to make some considerations about how you want to store it. If not, you can probably just put it into a local variable or session.
Related
I have a monolith web application powered by Laravel. Users access different forms and some of them have button on them that executes Ajax call to the back-end (example relative endpoint: api/external/get-current-temperature). A back-end function that handles the request than connects to an external service via API and obtain data, writes some log in database and pass data back to requestor (front-end user). But in order to execute any API call it has to authenticate and obtain a Token.
Question:
I have multiple users that can potentially request api/external/get-current-temperature at the same time. How should I handle authorization/token? Should I store it in database and check its expiration time before requesting a new one or what? How would I refresh it? - The external provide has no specific function that could be utilized to verify token. But I know for sure the token is valid 60 minutes.
The users of your application never have to be mixed up / mistaken with your foreign API. You can and should provide you own mechanism (i.e. tokens) to authenticate any users. If users are authenticated the external API is used, else an error-message could be provided by your application.
As users also fill several different form it's quite possible that you save some user-data. If every user has own authentication credentials it's easy and much more secure to provide only the user's own data. If you use for every user the same authentication token in your own application you might get the situation that one user can see data from another user.
So see it like this:
You / your application is the user of the external API, therefore you need only one authenticqation token for it. Your application users use the external API as a service and as that you should provide it in your app. The data though that are provided to the service might differ from user to user.
Example payment application:
The API is always the same, you as developer get an API key, but the payments are for every user of your application differently. As developer you might never even able to see, store or track the user-data that are exchanged between the foreign service and the user, but your app serves as hub and provides perhaps also some products or services that are considered in any payments.
I have started a PHP project (A Project Management Item Tracking Tool) using an API centric approach and have made a fairly good start.
I have created 2 GET the methods so far I want to restrict access but don't know where to start.
In the context of my database
Project is the container that encapsulates different actionitems.
Actionitems are 'assigned' to a user.
Users exist in a database.
Roles as assigned to a user. (User, Admin, Super)
User can only update their own item
Admin had create and update privilege
Super has total administrative privilege
My question is: Where should I start in PHP to only allow
accessing the api via proper users, either via a login api, or some
other means? Any help to get started would get me going.
To start I have successfully created an endpoint to access access resource (actionitems) using a JSON string to test the response.
Existing Endpoints I want to restrict
GET /api/actionitems/
With a general structure to access specific resources within a table as follows:
GET /api/actionitems/4
Note additional api endpoints should be accessed as follows
each route as up to 3 route tokens (following the /api/)
GET /api/users/123/actionitems (get all actionitems for user 123)
GET /api/users/123/actionitems?<more-filers> applies further filtering
You need to handle authentication and authorization for your APIs.
These are very basic steps to understand the solution:
Client calls login API using user credentials(username, password).
Server authenticates user credentials and generates a token.
Server stores this token in database against authenticated user id and responds to client.
Server already has authorization role rights to access different APIs associated with this authenticated user in database.
Client calls resource APIs using token provided by login API.
Server verify token in database and fetch user and user role rights against this token for authorization.
Resource APIs authorize and provides required data or perform actions according to authenticated user role rights.
There are multiple ways to achieve this in standardize way:
3 Common Methods of API Authentication Explained
JSON Web Token
oAuth2.0
You probably want to look at JWT tokens
https://jwt.io/
Here's some quick informations
An API with a token is stateless, you have to send the token on every request , generally in the Authorization Header, the token can contain a payload with some data like the user id the creation and expiration time.
On the server side, when you receive a token with a request you can just find the user id inside the payload and find the corresponding user in the database.
Since the token cannot be modified without the private key you can trust the data you receive.
Then you can just check if the user has some Admin or Super admin roles or if the item belongs to him and send the correct response.
Note: The payload inside the token is public meaning that everyone can read it, don't put any sensive informations.
If you want to use some long term authentication you can use refresh token with jwt tokens, they are stored in the database and can be used to create a new jwt token.
Hope this can help.
I am working with API that uses OAuth 2.0. Its' flow is like this:
In your application, you have a button which redirects you to the authorization server (APIs' in my case).
You either have to log in to APIs' website and give access to your application (press "allow" or "deny" button) or if you are already logged in, just give access to your application (press "allow" or "deny").
You get redirected back to your application with your new access token for making API calls.
Everything works for me, all is good but what I do not understand is how to deal with given access token so that the user, which has already authorized access to your application, would not have to give access again. Etc when he comes back to the application after a few days. It gives bad user experience (no one wants to grant access again and again).
Note: I am working with Quizlet API
First of all, Access tokens should be short lived. Consider it equal to short lived one time credential. If you are not convinced, check Azure AD token life time definitions linked here "Configurable token lifetime properties".
Its recommended to use define short lived access tokens, for example which expires after 1 hour. That way you avoid the complexity of storing them. You simply keep them in memory and use them to access protected resources.
what I do not understand is how to deal with given access token so that the user, which has already authorized access to your application, would not have to give access again. Etc when he comes back to the application after a few days.
Well, here you should be talking about Refresh tokens. According to OAuth 2.0 specification, its refresh tokens which have longer life time. If you check with my earlier reference to Azure, you see that they can live up to 90 days. For Google, refresh tokens expire after 6 months (if they are not used). One can still revoke them.
Now when you are using refresh tokens, you are not using them to access protected resources. Refresh token should be exchanged to get access tokens. So if someone steal them, they still need client authentication (ex:- client id, redirect uri & client secret) to obtain access tokens. Still, protecting them is a must.
Regardless, RFC6819 define some possibilities you can take on in section 5.3.3 to store secrets (tokens are secrets). You may use a client storage mechanism or utilise server backed to store tokens.
If your application has an back-end, one possibility is to correlate cookies to tokens. Cookie value could be a hash of the token which you have stored in back-end(probably in a database). When the back-end receive a request with a valid cookie value, it can retrieve the token stored against it. This is quite similar to "remember me" functionality.
What if you can't control token life time (They are by default long lived) ?
If you can obtain tokens hassle free, and if you can compromise end user experience, go for in memory storage where you will always retrieve new tokens for fresh access.
If you have a back-end for you application which can maintain the state between clients, push and store tokens at the back-end. Correlate client session with tokens, probably through cookies/sessions. Call secure APIs through back-end, without exposing stored tokens to client application.
I am very new to OAuth and I intend implementing an api for a frontend only (html and JavaScript) web app with login abilities using laravel Passport. Both the frontend app and the API server will reside on different servers. I have read a lot about different grants but still confused about which will be best suited for what I intend doing. Are the access tokens going to be stored on the front end (using local storage or cookies)? I am just confused about where to even start from.
I would suggest using the Implicit grant which is designed for browser applications. You can keep tokens in the sessionStorage (or the localStorage if you want to share them among browser tabs). OAuth2 tokens should sent as Authorization: Bearer tokenstring HTTP request headers, so cookies are not a good place for storing them.
There are two token types you can use:
Access token - if you want to use the token for authentication, access tokens hold scopes - information what actions the client is allowed to perform on behalf the person who was authenticated. Access tokens are often just random strings, so to validate it, the backend needs to ask the /token endpoint to get info about their validity and about the person who authenticated it.
ID token from OpenID Connect (OAuth2 extension) - in JWT form, ID tokens hold info about the person who authenticated them, can be validate offline, but cannot be used for authorization - they don't hold any scopes.
Bot token types have limited lifetime, you will have to get new token before the original one expires (using &prompt=none request see the OpenID Connect RFC).
I am using JWT token based authentication for the authenticating my REST APIs exposed to mobile apps. I have a login API where the user will be hitting to and get a JWT back as a response. App has to use the JWT token for the rest of the requests. One question that struck during the development is.
Once I give an authentication token to the user, he has access to rest of the set of APIs.
User 1 with JWT token T1 trying to access resources of user 2 is possible in my current design which is a flaw in my system. On each request do I have to check whether the user id in the token and the user id for which the process is requested matches and then proceed? or is there any better way this is been handled some other way?
I am using laravel framework with dingo rest and JWT lib.
Update
Eg :
I as an individual got the endpoints from the app. I logged in and received my jwt token which will be valid across rest of my resources. Now to get a list of products I have added using a different user id.I can do it this way
My JWT token in the header
GET /products/3 and 3 is not my user id!
In this case, Im just validating a jwt token, which will validate it and respond with the resource which is not MINE!
TL;DR: It is imho quite common to use it this way, you should be good the way it is!
More detail:
The point here is that the token is "obscure enough" so that there is an negligable chance a non-authorized user is obtaining the token from an authorized user. In your example this means, that user 2 can with a very high probabilty not guess the token that user 1 is using.
Of course this way may be prune to man-in-the-middle-attacks, so you should be sure to only transfer the tokens over a secure connection. I suggest "HTTPS only". Also, you may think about only sending and receiving the tokens in the header, so they are not exposed in any content views.
As a bit more background: Think about how PHP "standard" session cookies are working: The user (client) gets a session ID in a cookie and sends it back. This is basically the same as you are doing here with the JWT, as user 2 could also somehow steal the cookie from user 1 here, and act on his behalf. JWT even adds you a level with which you can easily confirm that you actually issued the token (provided you are using the RSA-keypair-style approach), which i think is an advantage over the PHP session ID cookie approach.