So before I start, I'm a bit of an OAuth2 newbie, so still trying to really wrap my head around the various permission scopes and grants.
I've managed to successfully implement an OAuth2 server using the Laravel OAuth2 Server package.
The current site I'm working on will simply dogfood from the API, using the client_credentials grant type. I've managed to get this successfully working and can make API calls with the provided access token.
However, I'm wondering how I can implement an architecture similar to Instagram, Soundcloud, etc, who don't require an access_token for basic endpoints, just a client_id. How do they do this? Is this a custom grant type?
Preferably, I'd only like to start requiring an access token when accessing private resources, such as those for modifying user information, etc. As far as I'm aware, for these I'd need to use the password grant type, which isn't a problem.
OAuth has a few flows such as 2-legged or 3-legged which basically tells the developer how many requests he needs to make to the server to get the resource he wants.
For example, in a 2-legged flow you send a request with your id and secret (first request), you get back an access_token and using that token you can make other request for the resource you want (second request).
Comming back to your Instagram example, you can think at using just client_id as a 1-legged OAuth flow, because you make only one request to server to get the resource you want.
You can use such a flow for less sensitive resources, like a profile photo or user's nickname for example.
The implementation of a 1-legged flow is simple:
- If the user_id is valid and the application doesn't need user approval to access requested resource, go ahead and show the resource.
So implementing a 1-legged flow consists in checking if the client_id is valid and checking if the requested resource needs user permission. That being said, you can use 1-legged for requesting a user profile photo, but you can't use the same flow for requesting the user's private messages.
You can read more about each OAuth Flow in The OAuth Bible.
You have two different resources on your server - a) Resources that need some access checks b) Resources that are publicly accessible.
Actions on resources that need access checks should require that a user has been identified via the OAuth header in the request. In the context of Laravel - this would be a route with the 'before' key specified as Oauth.
Actions that do not need access could glean context about what user is relevant by building your routes to accept an argument that gives you context about the user. Let's say that you have a profile that a user can see without any sort of access. Your API endpoint for a JSON representation of that could be /api/profile/[user_id], where [user_id] is the ID of the user profile you would like to see. For these routes where you do not care about access, you can leave off the oauth before filter in your route declaration.
Related
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'm trying to add an API on the top kong with using oauth2 authorization plugin of Kong. The steps
I have followed as per their Kong documentation :
Create an API and add oauth2 plugin
Create consumer
Create an application
I got client_id, client_secret, provision_key etc from the above steps, but I'm wondering that if I need to create oauth2 server at my end or kong itself configured it at their end and we just need to call their endpoints.
I'm building my APIs in laravel.
I think we spoke really briefly on Gitter, and there I already said that it depends on your use case. I'll do a brief rundown of typical use cases, and where you need which kind of additional implementation.
Machine to Machine communication
If you need two systems to talk to each other from the backends, and these systems trust each other, you can use the OAuth2 "Client Credentials Flow". In this case, there is no "end user" identity involved, only the two systems which explicitly trust each other.
For this scenario, Kong is everything you need - you just ask Kong's API Token end point (<address of kong>:8443/your_api/oauth2/token for URI based routing, or fqdn.of.kong:8443/oauth2/token if you're using host based routing) for an access token using your client ID and Secret, and you will get one back.
Example:
curl --insecure -d 'grant_type=client_credentials&client_id=<...>&client_secret=<..>' https://<address of kong>:8443/your_api/oauth2_token
Your backend service will get some extra headers injected, such as X-Consumer-Id and X-Custom-ConsumerId which maps to the consumer you created in Kong.
Confidential Web Application with End User context
In case you need to use your API from a confidential (=classic) web application, and you need to have an end user context with each call, you might want to use the OAuth2 "Authorization Code Grant". In this case, you will also need an Authorization Server which you need to implement yourself.
The Task of the Authorization Server is to establish an end user identity (mind you: This is not specified in OAuth2 how this is done, and is up to you; you can federate to some other IdP, you can ask for username and password,...) and then to decide on which rights (="scopes") the user gets when accessing the API. This is completely up to you, and part of your business logic how to decide this.
The flow goes like this:
You (re-)direct a user to the web page of the authorization server
The AS authenticates the user (by whatever means) and decides on the scopes (by whatever other means)
The AS talks to Kong on two different levels
Via the Kong Admin API, to retrieve the provision_key of the desired API
Via the [/your_api]/oauth2/authorize end point, which it uses to get a redirect URI which includes an authorization code, in the context of the authenticated user and his scope (scope and authenticated_userid); to call this end point, you will need response_type=code, client_id, client_secret, provision_key, authenticated_userid (whatever is suitable) and optionally scope (scopes need to be defined on the API as well if you want to use this)
If successful, the AS redirects back to the web application, using the redirect URI returned by Kong
The web app calls Kong's [/your_api]/oauth2/token end point with its client_id, client_secret and code, using the grant_type=code
Now you will have an access token (and a refresh token) which lets your web application access the API on behalf of the authenticated user.
The Authorization Server has to be implemented by you; this is not super complicated, but you still need to make sure you know how to authenticate a user, and/or how you delegate this to some other IdP.
Public Client (Single Page Application) with End User Context
In case you need access to an API from a Single Page Application (like from an Angular app or similar), you should look at the OAuth2 "Implicit Flow", which is a simpler flow than the authorization code grant, but which has other drawbacks, like not being able to use refresh tokens.
This flow works in the following way:
Just like for the Authorization Code grant, you redirect the user to the Authorization Server
The AS establishes identity and decides on scope (once again, this is up to you)
The AS calls the authorize end point, just like with the Authorization Code grant, but this time with response_type=token
Kong, if successful, will return a redirect URI which already contains a token
The AS redirects back to the SPA, using the redirect URI from Kong, which has the access token in the "fragment" of the URI (e.g. https://your.app.com/#access_token=<...>&token_type=bearer&...)
Your SPA will now be able to use the access token to access the API, just like with the Authorization Code grant, on behalf of the authenticated user.
The drawback with this approach is that you can't (that) easily refresh the token, and that it's somewhat less secure than the Authorization Code grant. But dealing with SPAs, there are not many other secure ways of delegating access to it.
Mobile Applications
The last scenario I would like to touch here is Mobile Applications, like Android or iOS apps. For these, the last OAuth2 flow, the "Resource Owner Password Grant" can be used. In short, with this grant you exchange the actual user credentials (username and password) against an access token and a refresh token, so that you don't have to store username and password on the mobile device more than temporarily.
This flow also needs an Authorization Server to be able to use with Kong, albeit a less complicated one this time, even though you must implement an additional token end point (in addition to the one Kong has), which is not ideally described in the Kong documentation.
It'd go like this:
The mobile app uses its client_id (NOT the secret, the secret should not be deployed with the application), the username and password to call the Authorization Server's token end point
The Authorization Server checks username and password (by whatever means, you know the story) and decides on the scope (...)
The AS talks to Kong over admin API again, getting the client_secret for the provided client_id and the provision_key for the desired API
The AS issues a call to Kong's token end point [/your_api]/oauth2/token, like this:
curl --insecure -d 'grant_type=password&provision_key=<...>&client_id=<...>&client_secret=<...>&authenticated_userid=<...>&scope=' https://:8443/your_api/oauth2/token
Note that this call does not contain username and password; those don't belong here, you must check username and password against your own source of identity, Kong will not help you with that.
This call should return both an access token and a refresh token which you then store (as safely as possible) on your device. These replace the username and password, which must not be stored on the device. The access token can as with the other end user context flows (Authorization Code Grant, Implicit Grant) be used to access the API on behalf of the authenticated user.
Using Kong with OAuth2 is tricky and involved, but Kong can really help getting this right and separate your concerns.
I am here with some general discussion very famous and interesting topic "Token Based Authentication".
I need my registered users to login with API. Scenario is quite simple, We want to pass our login details to Server. Server will check the credentials with database. If credentials are proper then Server will create "Session Id" and return back to user (client end). In subsequent requests user just need to pass that "Session Id" to authenticate and access protected data.
Plenty of people suggest about OAuth 2.0 and also some people suggest about Custom Logic. In custom logic they asked to be very sure about security. I read documentation of OAuth and it's good and descriptive. I'm also liking it to use. But wherever I search for OAuth authentication, they are giving example of third party login.
I had installed Php OAuth extension at my side for supporting this feature. In examples they asked to create Request Token first using "getRequestToken" function. Using that Request token they asked to call "getAccessToken" function to get "Access Token". Using that Access Token just need to call "fetch" to get protected data.
Now my questions are,
In my scenario, Do i need Request Token? Is that possible to get Access Token directly
What is OAuth Consumer Key and OAuth Consumer Secret key? Do I need such keys in my application? I believe it's used to allow third party applications only. In my case I'm the resource owner and i'm the consumer.
Do you guys have any example for me to study?
Do you know any well known framework for OAuth for PHP?
Is that need any additional database support except "user" table? For storing OAuth details?
Any additional documents to study for this would be highly appreciated.
I read different Grant Types in OAuth but confused how to use to achieve my approach.
Thanks in advance.
From what I read, you do not need OAuth at all. OAuth is need if there is a third party involved that needs access to your user resources.
As you mentioned, you just need a Login API something like https://myserver.com/signin?user=john.doe#gmail.com&password=12345
After successful login, the server generates a GUID and stores it against the user. You can call it sessionId/cookieId anything you like. Response could be something like '{user:john.doe#gmail.com; sessionId=KJN93EJMQ3WEC9E8RCQJRE8F9E}'
For subsequent calls, the sessionId can be passed in the header.
Server validates the session and lets the user in.
Addtional considerations:
I am assuming your server is HTTPS and hence the user/pwd on the URL are encrypted.
For security you might want to invalidate the sessionId have the sessionId renewed periodically.
Have a logout on which you clear the sessionId against the User.
I think it standard stuff if not the logging in happening via REST.
The requirement that I posted before to login with OAuth2.0.
Usually people assume that OAuth2.0 is only for fetching data by Third Party application from resource center behalf of Resource Owner. That approach is called Authorization Code.
OAuth2.0 has various "Authorization Grant". There are four types,
Authrozation Code
Implicit
Resource Owner Credentials (User Credentials)
Client Credentials
After research, I realize that "Resource Owner Credentials" is best suitable for me. I found one perfect library that helps you to understand background process internally. Here's the GitHub link to download.
Found two major issues here,
When I use my Access Token created by my Mozila in Chrome. Surprisingly, It's allowing me to access my private data from other browser.
I'm unsure but will this approach work same with AJAX type of calls (jQuery tool)
If anyone has idea then please share.
Thanks,
Sanjay
I'm currently building a web application which is an AngularJS frontend that communicates with a RESTful API built using Laravel. I'm making good progress, but finding it hard to get my head around how to handle user authentication.
I've been advised that I should be using OAuth for authentication, and I've decided to use it seen as it could be a learning experience for me as well. The package I'm using to handle this is oauth2-server-laravel.
The basic user story is that users can register their username/password combination for the application, and they then log into the application with that same username and password. They're only authenticated by their username and password, and not by any client secret. After login, they should be given an access token which will be send along with every future request to authenticate them on different API endpoints.
The OAuth2 library has a "password flow" grant type which seems to be what I need, however it also takes client_id and client_secret parameters, which I don't want. The request URI is something like this:
POST https://www.example.com/oauth/access_token?
grant_type=password&
client_id=the_client_id&
client_secret=the_client_secret&
username=the_username&
password=the_password&
scope=scope1,scope2&
state=123456789
But what I want is just:
POST https://www.example.com/oauth/access_token?
grant_type=password&
username=the_username&
password=the_password
How am I meant to provide a client ID and secret of a user that has yet to authenticate?
Is there a different grant I can be using, or is what I want to achieve just not suited for OAuth at all?
Take into account, that client id and client secret aren't parameters that you have to force your end-user to pass. They are static and defined in/for your client app (angular app in this case).
All you need to do is to create a record for your main app in oauth_clients table, and create a scope with full access in oauth_scopes table, and send this values when requesting token.
And that's all in fact.
Also, you may want to consider using implicit grant flow in case of building js-only application, because storing client secret and refresh token in a js app is insecure. Using implicit grant in a final product may look like login window on soundcloud and is more secure as the token is obtained server-side without exposing client secret.
Another way to go, if you still want to use password flow is creating a proxy for refreshing tokens. Proxy can hide your refresh token in encrypted http-only cookie, and your js-app don't ask your api for new token, but the proxy instead. Proxy reads refresh token from encrypted cookie, asks the api for new token and returns it. So the refresh token is never exposed. If you set token ttl for an hour let's say, then stealing a token would be quite "pointless*" in case of a normal application, and stealing refresh token would be "impossible*".
*Of course if someone really want he probably could hack it any way.
And yeah, i know this all looks a bit hacky - modal windows for logging in, proxy etc. But also searching on this topic i couldn't find any better and more elegant way of doing it. I think that's still a lack that all js-apps have to deal with if you want a token based authentication.
You are missing something with the OAuth specification. The client_id and client_secret are really important when asking for an access token when using the password method of OAuth v2. In fact, they are important for every method that gives you an access token. They identify the application or the server that has perform the request.
For example, let's say you have your API, 2 mobile applications and another server that do some tasks with your API. You will create 3 clients with their own client_id and client_secret. If your application has various access levels (they are called scopes in OAuth v2), the client_id corresponding to the other server will be able to call functions of your API that require the scope admin whereas your mobile application will only be able to call functions of your API that require the basic scope if you have defined scopes like this.
If your API grows up in the future, this is really essential. Another example, let's imagine you have given an API key (a pair client_id and client_secret) to one of your friend and he has build a nice mobile app with your API. If one day he starts doing naughty things with your API, you can't stop him very easily. Whereas you could have just removed his key pair if you had followed OAuth v2 principles.
OAuth v2 is not an easy thing to understand, take the time to read specifications and good tutorials before developing your API.
Some useful links :
The official RFC : https://www.rfc-editor.org/rfc/rfc6749
A tutorial on Tutsplus : http://code.tutsplus.com/articles/oauth-20-the-good-the-bad-the-ugly--net-33216
Just to add a bit to plunntic's excellent answer: remember "client" is not related to "user", so when I use a password flow I just define the client_id and client_secret as constants on the AngularJS app to tell the api backend: hey, this is the browser app that is being used to request a token.
I'm working on an API and considering using OAuth (3-legged approach) for authentication and authorisation.
This is the basic idea:
In order for clients (mobile app or web app), to use this RESTful API the user will have to be logged in using identity providers/servers such as Google, Facebook e.t.c
Essentially 3 parties will be interacting here:
The mobile / web app: The one trying to access my API
The API: The site that contains data for the app to run
The identity server: The site that will allow the user to login in order to access the API
Now, the way that I understand this process (assuming I do). This would be the flow (summarised):
The user will try to access data from the API (consumer);
The consumer finds that the user is not logged in;
The user gets a page (with service provider buttons such as Login with Google);
The user clicks the button, and the service provider returns a login form;
The user logs in;
The service provider returns a page asking for specific permissions;
The user grants permission;
The service provider returns an access token to the user;
The user uses the access token to try the request again to the consumer (API);
The consumer takes the token and verifies it against the service provider;
The consumer grants access to the user.
First
Is this process correct (on a higher level), or have I completely misunderstood the whole thing. If it is not correct: Could you offer some tweaks?
Second
After this whole process. How does the consumer communicate with the user? Will I have to be passing around a token on every request made (between the mobile app and the API)? Or can I just use the user details from the service provider to identify the user?
Third
How exactly does the consumer (API) verifies the token provided by the user against the server? Is this already implemented in OAuth, or will I have to do it myself?
Forth and last
In terms of implementation, what would be the difference between the client (mobile app / web app) and the consumer (API)?
I'm new to this, and I am trying to implement it in PHP (the API). If you have any references to PHP code (sample implementations) or external resources, I'd really appreciate it :-)
I am also new for oauth but I'll try to help.
First you could look here for appropriate libraries which could help.
As for me your oauth flow is correct. A good explanations you can also find here.
Keep in mind that authorization server should return an authorization code which you use for obtaining access token.
So your questions:
1) Follow the second link and there - "Authorization Code".
2) With every request to you API you should send your access token. Something like
http://<your api>?access_token=7f813af1-381d-4dd7-b70b-b6a8399b2c00
3) Just use the libraries from the first link. I hope that they have already implemented this. :)
4)Can't exactly understand what you mean. Your client must be able to obtain access token, store it and send it with requests. Your API server must be able to receive access token from client, and give access to api if the access token is correct.