Oauth 2.0 and OpenId Connect for REST API authentication and authorization - authentication

After having read books and watched videos on OAuth, OIDC, PKCE, JWT, etc. I still have no idea on how to use all of these for my app (a secured REST API).
My use case is fairly simple. I want my users to be able to login with Google, Amazon, Okta or whatever and the only info I want from them is the email address they used to login, nothing else. After their first login, their email will be added to a database and in a separate process I will grant them some permissions (what resources they can access).
So let's imagine a standard authorization code flow and let's fast forward to the access token part. The redirect URI has been called, we are in my client (somewhere is my backend/API) where I retrieve an access token. At this point the user has been successfully authenticated.
But what now ?
I don't care about Google anymore (do I still need the access token ?), but I still want to check if the user can use my API for each request and is able to access the API resources depending on his permissions.
How do I keep the user authenticated (for like 2h only) and check his permissions ? A session Cookie, a Token or something else with an expiration time ?
Do I need my own authorization server to check if the user has access to the resource he is requesting ?
Considering my requirements, do I need PKCE if the API is accessed from an SPA or a mobile app ? Wouldn't the authorization code flow be enough - the SPA or mobile app retrieve an authorization code, then call the callback endpoint from the API ?
And the more important question is, do I ask the right questions or am I completely off track and it's not how it's supposed to work ?

In terms of your questions:
Your API needs an access token on every request
A stateless session is managed by sending the access token on every request
It is recommended to use your own Authorization Server that manages redirecting to social providers - this will simplify your UIs and APIs which only need to handle one type of token - also this means you are in control of the tokens your apps use
Yes - use PKCE for public clients - the Authorization Server and UI security libraries will handle this for you
Your use case is not simple at all on a technical level and requires a lot of understanding. A good starting point is to understand these aspects:
Role of UI and what a coded solution looks like
Role of Authorization Server and its configuration
Role of API and what a coded solution looks like
Open Id Connect messages used
These links of mine may be useful for browsing:
Initial code sample and tutorial
Message Workflow including PKCE
Given an access token, both the UI and API can potentially get the email via step 12 in the second link to lookup user info.

Related

How does OAuth work API to API without interactive users?

I have a background task that runs periodically which needs to connect to a customer's Apigee OAuth2 protected API. From my understanding of OAuth2, a user must go to a sign in page on Apigee, and it will redirect to a return Url with a token. This is the way I have used previously on website projects. But in this scenario, there are no users, no website, and no return Url, it is just some code making a http request.
Is the above possible to do? Every google search I make is all about users logging in manually and getting a token to a return url.
I found some mention of 'Flows' and maybe there is some other 'Flow'? but its really hard to get a clear understanding of how it works because guides are focused on user interactive websites.
OAUTH 2.0 is an industry-standard for authorization. OAUTH 2.0 supports many authorization grant types, namely they are;
Authorization Code
Implicit
Resource Owner Password Credentials
Client Credentials
[Note that you may come up with your own custom grants as well if you are building or extending your authorization server - however it is beyond the scope of this question]
In the example you have provided, you are using the Authorization code grant type where you redirect to APIGEE and getting an authorization code. The APIGE server acts as the "intermediary between the client and resource owner" in OAUTH 2.0 terms.
For your new requirement, you should consider using the client-credentials grant type where the client is provided a client key and a secret. The client has the responsibility of calling the authorization server (like APIGEE in your previous example or anything else) and getting a token and then using that token in the subsequent requests.
I recommend you to read the ietf standard for oauth 2.0 to get a better understanding - Refer https://www.rfc-editor.org/rfc/rfc6749.
Make sure to read on "Roles" in this link well before diving onto the content of this document.
Good luck!

Do I not need to secure my API endpoints (resources) with OAuth 2 access tokens?

There are multiple partied involved in OAuth2 conversation. Consider the
following diagram from the article here
Consider that I have an application that has data for restaurants and has APIs related to it. Let's call is restaurants APIs. Let us assign some role to each party in context of this example
User - our chefs, who have some recipes in restaurant
Application - Web client written in HTML5, JS, CSS that our Users use to interact with APIs
OAuth Endpoint - Google (who acts as Authorization Server)
API - My application API keeping all data for chefs
The workflow for Implicit (as per above diagram in the link) states the Application gets the access token and then the Application(browser) calls API (my application with chefs recipes) and gets the data back.
Questions
Shouldn't I secure my application endpoints or rather just believe the accesssTokens? Yes, the trust is established between Application and OAuth Endpoint (Google), but there is no trust developed API and Application by confirming the validity of accessToken with OAuth Endpoint (Google)?
If I should secure my application API endpoints, shall I have a /login endpoint for my APIs where my application accepts accessTokens, validate and create a JWT based headers for clients to use for further communication with protected resources like /recipes.
Looking forward to your ideas here.
Thanks in advance
TL;DR - don't blindly trust the access tokens. Ask Google to reveal the user/email associated with them and the client ID that was used when generating them. You can still provide a /login endpoint for scalability purposes mostly.
Let's deal with the core security first
OAuth is a delegation protocol, not an authentication protocol. To quote from the OAuth website:
The OAuth 2.0 specification defines a delegation protocol [...] OAuth is used in a wide variety of applications, including providing mechanisms for user authentication. [...] Let's say that again, to be clear:
OAuth 2.0 is not an authentication protocol.
Because it's not an authentication protocol, your app/API never learns who the user is. It just gets a token. Delegation in this context means that OAuth lets App A request access to resources in App B that belong to a User, by having the User authenticate to App B and then passing the token back to App A. In your example, it can provide your web app with access to Google resources (email, photos, etc. - depending on the required scopes) that are owned by the Users (chefs).
Note that this isn't what you are doing here, since you're accessing resources managed by your app, not by Google. In particular, as you correctly identified, the access token means nothing to your API. I could just as well give it a random string.
You might be tempted to use the following scheme:
Implement the implicit scheme as described in your question.
Have the API server validate the access token with Google, and ask Google for the name or email associated with the token. This will be the identity of the user who actually logged in to Google, and you can then decide whether or not to grant permission to that user.
The problem with this approach is that many apps use OAuth with Google, and so many apps will have Google access tokens that don't belong you app. How can you tell the difference?
You can ask Google, when you present it with the access token, to also provide you with the client ID that was provided when this token was generated (see how your diagram indicates that the client ID is sent?). Since that client ID uniquely identifies your app, then your API can tell that it's been given tokens that only came from your app. Note that this critical part of the OAuth flow is very different in mobile apps which is why the implicit flow should not be used with mobile apps (but it's fine with web apps).
Note that your client ID should be considered common knowledge (e.g. it's found in the .js files on the machines performing this flow), but it cannot be spoofed because as part of the OAuth flow, the user's browser will be redirected to a URL that is pre-configured in Google and belongs to your app. So even if a malicious app uses your client ID, Google will still send the token to your app.
Other practicalities
The above requires you to issue a call to Google on every API call, or at least cache the valid access tokens (which means you keep state, which is a bummer for scalability). If you want to avoid this, you can create a /login endpoint which generates a JWT. Note that you'll still need to validate the access tokens upon login.

Understanding Oauth2

I am creating a REST inspired API for a Learning Management System. It will expose data such as users, classes, grades, courses etc. I have defined all the resources I want to expose, given them each an endpoint URL, and defined the JSON resource structures that are returned.
I now want to understand how to secure the API using Oauth2 (I don't want to use Oauth1). Am I correct in the assumption that my API will play the part of both the Authorization Server & the Resource Server? Also, what grant type / flow should I be researching?
A lot of the tutorials seem to focus on using Oauth2 to login using facebook credentials etc - but I just want to use it to secure my API and allow my users access to my API (either through a client, or directly). The access permissions for the API should follow the individual users access permissions that are already handled within our system.
Sorry for the scatter-gun questions - I just don't understand oauth2 enough to know where to direct my research. Any help would be greatly appreciated, and any pointers to simple tutorials for the correct use case would be great too.
FYI - The system is built on a LAMP stack using Drupal 6 (old, I know).
Well your assumption is correct the authorization server and the resource server can be on the same server or in the same API.
So how the OAuth2 basically works you have some kind of client(Server, Browser) Authorization API will authorize with Access Token to use your resource API which is then sent in the the Authorization HTTP header on every resource request.
So what I success is that when the user logs in, you identify the user and generate the Access Token immediately to the client. Now you can put some data inside the Access Token e.g. userId, permissions etc. Now when the Access Token hits your resource endpoint you can identify the user and check the permissions. Also you can just make the Access Token dumb so it doesn't contain any data then when you validate it from Authorization API(on Access Token creation you have to store info about the user to Authorization DB), you can get the info you need on the response e.g. userId, permissions etc.
What grant type flow to use, this is basically up to question what kind of clients are using your Authorization API and how secure you want the Authorization to be. E.g. implicit grant is for browser based clients which can handle redirections and e.g. Client Credentials grant is for (server-to-server) communication.
Reference here
To start with, you can use existing providers like WSO2 API Manager for supporting your system. It is well documented and has many REST APIs for this.

Login to Single Page Application with Google authentication and Google Oauth 2.0

We are developing an SPA - full client base javascript application and need to authenticate our users to get access to the internals.
As I found from the search we can outsource our authentication mechanism and use Google accounts for that. I learned from this site
https://developers.google.com/accounts/docs/OAuth2Login -
How to deal with Google API and mechanism for authentication.
In the short word, we need:
send request to google url with params to ask user to allow SPA use their personal data
in case of success we get a token from Google
we may use this token to get access to API we were asked and work with it.
This is described well and I understand it and have some JS code to make it happen.
What I do not understand.
I have an application with it's private data. I want use user's e-mail as the login, or user id (doesn't matter how to call it) to access app's internals, such as user's created tasks, user's profile, etc. So, to display user's created tasks in my SPA I need query database with the user's e-mail.
I imagine the next scenario:
user click Login with Google button
we obtain an token - this means user was authenticated successfully
we persist user and his e-mail to work with SPA
when user click Logout we clear all access data
Where should I persist this data?
In case of Forms Authentication I understand that we pass login/password to server and if they match the database we create Forms Ticket and store it in cookie.
Is there any similar case with Google's auth? If I'll store user's email in cookie I think that's not very good from security reason. If I'll save a token - I'm not sure why I need it and how to use it in my SPA, I'm not using any Google API after authentication.
Do you have any example case how do we build our process in similar cases?
Thank you.
If all you need is the user's email address, then you would be better off using OpenID instead of OAuth. OAuth provides access to a user's account and services, scoped to a specific resource or set of resources. OpendID is designed just for logging into a third-party service. You can then extract the user's ID and email address from the OpenID login. Note: The ID will always be sent but the email address has to be explicitly requested during authentication.
Google also supports a hybrid OpenID+OAuth scheme that lets you piggyback OAuth requests on top of an OpenID login if there is some resource you need to authenticate to. Take a look at the authentication document to get an idea of how both protocols work and which is better for your scenario.
Once you have the email address returned, you probably shouldn't persist it in a cookie. The normally recommended way to handle it is to add it as a session parameter. That way only the session cookie is stored on the client, and the server can use it find the values it needs. This answer has a good explanation of the differences and when you want to use sessions versus cookies.

how can I authenticate a user from a web app to an API?

It seems to be a widely asked questions and after having read tons of documentations on the subject, I'm still not sure to have understood everything correctly (I assume that being dumb is a possible answer ;)).
I'm trying to build an API that will provide a service to users. The users will be connected through Facebook or any OpenId provider (I separate Facebook since their implement their own connecting system).
(I think it's a good way because I will not store the user's password and finally will have less problem in case of a similar Gawker issue.)
When a request is made from the client (web app, mobile app, whatever) to the API, an indicator must be sent with the request in order to identify which user is using the app. This is generally used via a token, defined during the Authentication.
But regarding the Authentication, I can't find any valuable example, tutorial, explanations about how to implement it correctly.
I'll (try to) explain :
In my (wonderful world of happy care bears), I structured my project in various parts :
A RESTful API
A web apps that will use the api. Ideally, I was thinking about making a complete html/css/js project, without any server side work (php/python/java or whatever)
A mobile application
An windows/mac/linux application
As far as I saw, every time someone ask how to implement a RESTful API authentication, three major answers pops out :
The HTTP basic( + preferably SSL)/digest way
OAuth
OpenId
Since I will not store the user's password, the first one is out for me, but the two other leave me perplex.
But OAuth and OpenId are not the sames, one (OpenId) stand for the Authentication (that the base of the questions) where the second (OAuth) stand for the Authorization!
When Twitter implements OAuth for their API, they are not implementing an Authentication system, there are setting up a way to indicate their users that the application X want to have access to the user account (in various level of access). If the user is not currently logged in Twitter, he will first have to authenticate himself, and then authorize the current application to access his data.
So, just to clear things up, OAuth is NOT an authentication mechanism, it's a :
An open protocol to allow secure API
authorization
(source: http://oauth.net/)
Then, the only way to authenticate a user would be using OpenId. And then, the hell comes true.
If I take as an example a web application that is exclusively made of html/css/js, with no server side components, communicate with an API.
The web app must indicate to the API that the user currently using the API is mister X.
To do so, the web app show a popup containing a list of OpenId providers, asking the user to authenticate himself. The user click on one of them, get redirected (or a new popup open up) to the OpenId provider, indicate his login/pass, get authenticated by the OpenId provider, that return the success with a token (I simplified the communication).
That's great, the web app know now that the user is really mister X. But the API still have any clue !
Finally, my question is quite simple : how can I authenticate mister x through the web app to the API via OpenId and after that, how can the web app and the api keep the information that this is mister X that is currently using the web app and of course, the API.
Thank you very much for your help !
-edited format
You don't really want to login to the API using OpenID. As you said, OpenID is for Authentication, i.e. Who, while OAuth is for Authorization, i.e. am I allowed? But your structure suggest you'll be using an API as a backend and a web app as a front-end.
The best way then is to use OpenID on the web-app to authenticate the user, and then the web-app connects to the API and stores the OpenID credentials. The web-app then knows who the user is, and can provide the service. The API has nothing to do with the user, except that it stores its data.
The fundamental difference between OpenID and OAuth is its use. In your situation, you could have something like that:
-------- --------- -------
| User | <------> | App | <--------> | API |
-------- OpenID --------- (OAuth) -------
The User never interacts directly with the API: who would want to manually send HTTP request? (lol) Instead, the service is provided through the app, which can optionally be authorized using OAuth. However, in the case of a single app accessing the API, you can make the app <=> API connection internal and never expose it.
(If you don't want to read, the list bellow sum up the whole idea)
A possible solution (tell me if I'm wrong) would be to display the login form in the consumer (web apps, mobile apps, etc), the user click on it's provider (myopenid, google, etc) that opens a popup to do the login.
The tricky part is that the return_to parameter would be set to the API, not the website
The API will then resend the check_authentication and get the is_valid:true (or not).
During this step, the app would query the api to a specific url that return the state of the authentication (processing, failed, success). While it's procesing, an indicator is displayed to the user (loading gif), and if it's success/fail the result is displayed to the user.
If the api receive a is_valid:true, then it will ask informations about the user to the openid server, like email, firstname, lastname, and compare them with it's user's database. If there is a match, the api create a session between itself and the app, if the user is new, it create a new entry and then the session.
The session would be a unique token with a specific duration (maybe equal to the openid server assoc_handle duration ?)
It seems to be something possible, but I'm not an expert in security.
In order to explain things simplier, here is a little "map" :
Note: Provider is the OpenId server (that provide the informations about the authentication)
The User go the webapp and click on the login icon of his provider (Google for ex)
The webapp opens a popup containing the provider login page and access page, and specify a return_to to the Api
The provider sends informations to the Api
The Api validate these informations via the check_authentication
If not valid, the API indicate to the webapp (that ask the api every x seconds) the failure
If valid, the Api asks informations about the user to the provider, like email, display name, etc
If the user exists, a session is created
If the user is new, he's added to the database and the session is created
The Api returns the state of the auth (in this case, success) with a token session that will be used by the web app for further requests.