OAuth Security with Pre-Configured Authorization - rest

I have a scenario where a user has logged into to a web application (authenticated with OpenID Connect) and then needs to access data from a separate REST service.
The REST service needs to determine whether or not the user has permission to access the requested data, but if the user does have permission, then it should grant authorization to the web application without requiring the user to interact with the UI.
Essentially, what I need is a two-legged OAuth solution where the client/relying party is fully trusted but the user, who's already been authenticated, is not.
Going in, I assumed that OAuth could accommodate these requirements, but none of the grant types seem to match the requirements:
Authorization Code is the opposite of what I need, as the user is pretty much automatically trusted but the client is not, requiring that the user grant access to the client via a web form.
Client Credentials trusts the client (which is what I need) but does not give the service an opportunity to determine if the user has permission to the resource (user auth tokens are not passed to the service, making all requests essentially "anonymous").
ROPC (Resource Owner Password Credentials) would appear to be the only option, but requires the web application to know and possibly store the users' login credentials (which is untenable).
Is this a gap in OAuth? Or am I misunderstanding these grant types? If OAuth can't support this scenario, is there another widely adopted open standard that I've missed?
Of note: I only own/control the web application, while the customers (all of which are businesses) own/control both the authentication servers and the REST services. Therefore, a shared, non-proprietary standard is necessary so that our customers will know how to configure their services (IBM, Microsoft, whatever) and so that I'll know how to pass along any authentication tokens, etc.

I think this is possible using normal OAuth2 flows. You have your web application use the code authorization grant to get a token to call the API on behalf of the user.
Your web application makes the call to the API attaching the JWT token in the Authorization header. If the REST service determines the user does not have permission to access the resource, it returns a 401 Unauthorized HTTP response code.
Your web application handles the 401 response by going back to the authorization server and using the client credentials grant to get an access token to call the REST API on behalf of the client itself.
As both grants allow you to get a refresh token, you should be able to switch between access tokens easily.

If there is no trust relationship between the web application and the REST service, there's no way around using the Authorization Code grant since the user needs to be involved anyhow to allow the web application to make the call on behalf of the user.
If there is a trust relationship between web application and REST service you should be able to use the regular OpenID Connect flow to get an access token to the web application at login time that can also be used in calls towards the REST service.
You may pass on the user information as part of a JWT (i.e. a structured) access token that is signed by the web application itself or the OP; that would be OAuth 2.0 compliant. See https://www.rfc-editor.org/rfc/rfc6749#section-1.4 and May an OAuth 2.0 access token be a JWT?.

Related

How to perform user registration and authentication between a single page application and a REST API with OpenID Connect

Consider that we have:
An SPA or a statically generated JAMStack website.
A REST API.
The website is being served with nignx that also reverse proxies to our API.
--
It is required that a user should be able to register/authenticate with an identity provider (say, Google) through the OpenID Connect protocol. For the sake of simplicity, let us assume that the user has already registered with our API.
Talking about authentication using OIDC, from what I have read on the subject, the steps you take are the following:
Register the application with the IdP and receive a client id and a secret.
When the user initiates a login (with Google) request on the API ('/api/loginWithGoogle') the API sets a state variable on the request session (to prevent CSRF) and redirects the user-agent to the IdP's login page.
At this page, the user enters their credentials and if they are correct, the IdP redirects the user to the callback URL on the API callback (/api/callback).
The request received on the callback has the state parameter (which we should verify with the one we set on the session previously) and a code parameter. We exchange the code for the identity token with the authorization server/IdP (we also receive access/refresh tokens from the auth server, which we discard for now because we do not want to access any APIs on the behalf of the user).
The identity token is parsed to verify user identity against our database (maybe an email).
Assume that the identity is verified.
-- The next part is what's giving me trouble --
The documentation that I have read advises that from here we redirect the user to a URL (e.g. the profile page)and start a login session between the user agent and the API. This is fine for this specific architecture (with both the SPA/static-site being hosted on the same domain).
But how does it scale?
Say I want to move from a session based flow to a JWT based flow (for authenticating to my API).
What if a mobile application comes into the picture? How can it leverage a similar SSO functionality from my API?
NOTE: I have read a little on the PKCE mechanism for SPAs (I assume it works for JAMStack as well) and native mobile apps, but from what I gather, it is an authorization mechanism that assumes that there is no back-end in place. I can not reconcile PKCE in an authentication context when an API is involved.
Usually this is done via the following components. By separating these concerns you can ensure that flows work well for all of your apps and APIs.
BACKEND FOR FRONTEND
This is a utility API to keep tokens for the SPA out of the browser and to supply the client secret to the token service.
WEB HOST
This serves unsecured static content for the SPA. It is possible to use the BFF to do this, though a separated component allows you to serve content via a content delivery network, which some companies prefer.
TOKEN SERVICE
This does the issuing of tokens for your apps and APIs. You could use Google initially, though a more complete solution is to use your own Authorization Server (AS). This is because you will not be able to control the contents of Google access tokens when authorizating in your own APIs.
SPA CLIENT
This interacts with the Backend for Frontend during OAuth and API calls. Cookies are sent from the browser and the backend forwards tokens to APIs.
MOBILE CLIENT
This interacts with the token service and uses tokens to call APIs directly, without using a Backend for Frontend.
BUSINESS APIs
These only ever receive JWT access tokens and do not deal with any cookie concerns. APIs can be hosted in any domain.
SCALING
In order for cookies to work properly, a separate instance of the Backend for Frontend must be deployed for each SPA, where each instance runs on the same parent domain as the SPA's web origin.
UPDATE - AS REQUESTED
The backend for frontend can be either a traditional web backend or an API. In the latter case CORS is used.
See this code example for an API driven approach. Any Authorization Server can be used as the token service. Following the tutorial may help you to see how the components fit together. SPA security is a difficult topic though.

REST API user and client authentication

I am building a REST API as the backend for a mobile app. I would like to check if the requests made to the API are coming from our mobile app. However, the API will require end users to login in order to access certain endpoints.
My questions is, how could I authenticate all incoming requests to make sure they are coming from our own app, while also authenticating the end users for some requests?
I was thinking of sending an API key with all requests in the Authentication HTTP Header to authenticate the mobile app, and (separated by a comma) also send along a JWT for authenticating the end-user. While this could work, it seems a bit "hacky".
What is the standard way of authenticating both the mobile app and the
end-user of the mobile app at the same time?
Using an application token and a user-specific session token is one method of separating authentication of the two. The application token would be unique for your application, and should be obfuscated so that inspection of the client's binary would not lead to easy detection of the token. The user-specific session token should be generated when the user is logged in. The client adds this user session key to future API calls, the server will check if the session key is valid, and can use it to look up any session state stored for the client.
However, optimally, you would implement the full oauth2 spec. as outlined in this ultimate guide to mobile API security:
Here’s how OAuth2 token authentication works from a user perspective
(OAuth2 calls this the password grant flow):
A user opens up your mobile app and is prompted for their username or email and password.
You send a POST request from your mobile app to your API service with the user’s username or email and password data included (OVER SSL!).
You validate the user credentials, and create an access token for the user that expires after a certain amount of time.
You store this access token on the mobile device, treating it like an API key which lets you access your API service.
Once the access token expires and no longer works, you re-prompt the user for their username or email and password.
What makes OAuth2 great for securing APIs is that it doesn’t require you to store API keys in an unsafe environment. Instead, it will generate access tokens that can be stored in an untrusted environment temporarily.
This is great because even if an attacker somehow manages to get a hold of your temporary access token, it will expire! This reduces damage potential (we’ll cover this in more depth in our next article).

How to protect bearer tokens in a web app

I am trying to implement the Authorization Code flow described in RFC 6749 (OAuth 2.0) for a JavaScript-based application. I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end. Then all requests from the front-end to any protected resources go via the web server back-end, which attaches the access token to the request and proxies it on.
My question is how do I let the JavaScript front-end make use of these tokens in a secure way? I assume that I have to do something like set up a session on the web server and pass back a cookie that identifies the session. But this means that the JavaScript application then has a cookie that gives them the same privileges as if they just had direct access to the bearer tokens stored in the web server. How does having a web server to hold the tokens give extra security?
I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end.
No, it is a misunderstanding of the OAuth2 flows and goals.
Here is the OAuth2 main goal: your application (which can for instance be a JavaScript program running in the browser, a web server, both, etc.) MUST NOT need to know the user's credentials (most of the time a login/password pair) to access the service on behalf of the user.
Here is the way OAuth2 must be used to achieve this goal:
according to your needs, that is having a Javascript-based application running in the browser (i.e. not a node.js application), you need to use the OAuth2 implicit flow, not the authorization code flow. But of course, because your application is running in the browser, it will not be able to persist the credentials to access the resource offered by the service provider. The user will have to authenticate to the service provider for each new session on your application.
when your application needs to access the service provider when the user is not logged in, or when your application is able to persist credentials (because your application has its own credential system to identify its users), your application does not only rely on a JavaScript program running in the browser. It may rely only on a web server, or on both a web server and a JavaScript program that talks to this server. So, in those cases, you must use the authorization code flow.
So, as a conclusion, you have decided to add a web server to your application because you thought you had to use the authorization code flow. But in your case, you probably do not have to use this code flow, therefore you should select the appropriate code flow for your application: implicit code flow. And this way, you do not have to add a web server to run your application.
How does having a web server to hold the tokens give extra security?
This does not give extra security. Having a web server to hold the tokens is simply a way to let your application access the service on behalf of the user, in the background, when the user is not logged on your application.
While I agree with Alexandre Fenyo's comments, I just want to add the 2021 version. You should no longer be using the implicit flow as this is no longer considered secure.
For scenarios such as this where a JavaScript application has to handle tokens I would suggest using the Authorization Code flow with PKCE instead: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce

Azure Graph API - Query user information

I'm trying to figure out how to use the Azure Graph API to query a user's full name (first and last) from a given username. I understand I can do this with the following Graph API call...
https://graph.windows.net/myorganization/users/{user_id}?api-version
However, I am not sure how I go about getting an access token to use with this, because this process will be called without a user logging in, which is usually how we obtain an access token.
Is there anyway I can pass a username/password to a given URL using cURL or something and obtain an access token that way, so it is done behind-the-scenes?
There are two main authentication methods which are supported by OAuth 2:
Authorization Code Grant Flow
Client Credentials Grant Flow
The first flow requires a user agent to be present to sign into the client service and results in a delegated token. The second method does not require a user to sign in, as it only authenticates using the client secret; this results in an app only token.
If you want to create a background service that captures data from the AAD Graph API, you can absolutely do this using the Client Credentials Grant Flow, which does not require a user to be present at any point during the authentication flow.
You simply need to configure your application to to have app only scopes. Read here: Permission scopes | Graph API concepts. App only scopes all require tenant administrators to consent to the application in order to get access to data.
Finally, I feel I must mention that there is another less used flow specified in the OAuth 2 spec: Resource Owner Password Credentials Grant. This flow specifies how a client application who has knowledge of a user's username and password could directly pass those parameters and get an access token on behalf of the user. However using this flow is not good practice at all.
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
We support this in our V1 endpoint, but not in our new V2 endpoint. You can read this blog to learn more.

Is it possible or even advisable to use OAuth 1.0 to secure a RESTful web API without redirecting the user to a separate provider?

I am in the process of building a RESTful web service using ASP.NET Web API, and I am considering using OAuth 1.0 as an authentication mechanism to secure the service. Our API would also be maintaining the credentials store and would therefore be the OAuth provider. Client applications using our API would be used by end users who would have to authenticate using a username and password, so I assume the client app is considered to be an OAuth consumer. The client application would make an API call to retrieve an unauthorized request token, then send along the user's credentials with the token to get an access token.
Ultimately, I could see other 3rd party applications wanting to access our application through my API, and they would use OAuth with the redirection with our application being the credentials provider.
Is this a viable way to use OAuth? Will something like DotNetOpenAuth support this scenario?
We have decided to implement OAuth 2.0, which supports various workflows, one of which includes a Resource Owner Credentials flow that allows the client to pass user credentials to the authorization server in exchange for an access token. This will serve our purposes.