Requiring the ID token too to access an API endpoint - http

Let's take an example where we have an SPA accessing an API using the OIDC implicit flow.
Since OAuth scopes are coarse-grained, it is often necessary to perform additional authorization on the resource servers. This can be the case for example when accessing dynamic resources (e.g filesystem) via an endpoint - where access is restricted by permissions tied to the userId, but it is not practical to use OAuth scopes only because of the dynamic nature of the resources.
In these cases the endpoint itself can be protected by an OAuth scope, while access to the resources that the endpoint operates on (e.g files) will be granted based on the userId. Hence the user's identity must be securely sent in the API request.
An obivious choice can be to send the ID token that was obtained when authenticating, together with the access token that was obtained at the same time.
There is a standard way for sending the access token in a HTTP request (the Authorization header), but is there one for the ID token? Or should I just make up a header name like 'X-Identity'?

To answer the question: there is no standard for passing the ID token in an HTTP request.
But arguably there doesn't need to be one: in this case you may not need OpenID Connect since scopes are not the only information that can be associated with an OAuth 2.0 access token as you seem to suggest.
You can "associate" the userId with the access token so that the Resource Server can grant the Client access to the protected resource based on the identity of the user who granted the access token to the Client.
The "association" is implementation dependent: the access token can be a JWT that contains the userId claim or the access token can be an opaque value that the Resource Server can introspect/validate at the Authorization Server to obtain the information associated with it.

Instead of passing it in the header, you can pass it as a query parameter:
curl "https://resourcePath?auth=<ID_TOKEN>
Here's the reference:
https://firebase.google.com/docs/database/rest/auth#authenticate_with_an_access_token

Related

Why connection token passed in the URL in Signal R?

I got a website to handle all security issues raised by a software during Pen Testing. Please refer to the following screen shot:
jquery.signalR-2.4.1 is being used in the project (ASP.NET MVC). I need to give explanation to the security team about the use of above URL, why it is showing under a GET request. Is there any threat for the application? If yes how to remove the connection string from the query string inside the URL? If it's an inbuilt process or method what's the exact use?
It's a connection token, not a session/security token. This is documented in Microsoft's SignalR security section of the documents. I would refer your security team to this information as they are not aware of the difference here and how it is used. Especially the bolded portion below:
Here it is in case the link changes -
SignalR's connection token isn't an authentication token. It is used to confirm that the user making this request is the same one that created the connection. The connection token is necessary because ASP.NET SignalR allows connections to move between servers. The token associates the connection with a particular user but doesn't assert the identity of the user making the request. For a SignalR request to be properly authenticated, it must have some other token that asserts the identity of the user, such as a cookie or bearer token. However, the connection token itself makes no claim that the request was made by that user, only that the connection ID contained within the token is associated with that user.
Since the connection token provides no authentication claim of its own, it isn't considered a "session" or "authentication" token. Taking a given user's connection token and replaying it in a request authenticated as a different user (or an unauthenticated request) will fail, because the user identity of the request and the identity stored in the token won't match.

AWS Cognito hosted UI returning id_token in URL

I am using AWS Cognito's hosted UI for user login. The id token is returned as part of the URL as described in https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html. Namely,
You can find the JSON web token (JWT) identity token after the #idtoken= parameter in the response. Here's a sample response from an implicit grant request. https://www.example.com/#id_token=123456789tokens123456789&expires_in=3600&token_type=Bearer
However, putting sensitive data in a query string is considered a bad practice (Is an HTTPS query string secure?). Does AWS Cognito support a more secure way of returning the id token?
Instead of token you can ask cognito to send you the Authorization code.
From Documentation:
The authorization code grant is the preferred method for authorizing end users. Instead of directly providing user pool tokens to an end user upon authentication, an authorization code is provided. This code is then sent to a custom application that can exchange it for the desired tokens. Because the tokens are never exposed directly to an end user, they are less likely to become compromised.
Source: https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/

Identity Server 4 reference token and security

In my project I use the identity server 4, an SPA (Angular) and a protected API (PHP). I decided me to use the reference token. My Client (SPA) works with implicit flow (is it correct not to use a client secret?) And gets the access token after login (call the authorize endpoint). After that the SPA have to send the token to the API so the API can ask the identity server 4 (introspection endpoint), if the access token is correct and the API can get access to the user´s information.
Now I want to know, how to secure the communication. Because the access token has no information in it, is it necessary to send him with jwt to the API or is it enough with a normal JSON send? As I understand the API must call the introspection endpoint with jwt bearer.
Is this method secure or what else should I do?
There is no such requirement - the API to call the introspection with a JWT. If the API is set to work with JWT's it will just verify the signature of the token with the public key from IDS. If it is set to work with reference token - it will call the introspection, to get the user info (which is the payload of the JWT). Reference tokens documentation.
Your API needs to be protected with its ID and Secret, so that you can call the introspection endpoint.
When calling it you send the reference token (it is still an access token, but it is not a JWT), the client_id and the client_secret. The content-type of the request should be application/x-www-form-urlencoded and it should be POST.
The response from the introspection endpoint is the user info.
No need of additional security - the client ID and Secret are the security, and the call is made server-to-server from API to IDS (assuming you are behind https of course)

Why does OAuth use HTTP GET to return the access token?

In the OAuth authentication flow, if permission is granted by the service provider, the authorization redirects to a app-specified redirect URL with the access token (e.g. yourapp.com/redirect/?token=deadbeef).
Now the app has to store that token in some way – either directly store it in the database or start a session with the service provider. Doesn't this contradict the "laws" of HTTP methods, specifically that GET is supposed to be a read-only action?

Authenticating with Web API

I am using ASP.NET WebAPI for a web service that I am building. He web service will use the Identity service to authenticate users.
I am a bit stuck as to how to authenticate users externally. Our current system is very basic- we send a username and password in the XML request as a separate field and it is all done in 1 request.
From what I can see from looking on Google, the best way is to request a token from the Ali and then pass this token in subsequent requests. Is there a way where I can do it all in 1 request (that is, send to the API my request for data as well as the username/password or perhaps an API key in a single request?)
From what I can see from looking on Google, the best way is to request
a token from the Ali and then pass this token in subsequent requests.
Is there a way where I can do it all in 1 request (that is, send to
the API my request for data as well as the username/password or
perhaps an API key in a single request?)
I'm not sure why your web service want to know user's username and password in Token based Authentication.
In Token based Authentication, your web service should not ask for user's username and password.
Instead, user first verifies the user name and password using a token issuer that your service trusts.
Upon successful verification, the token issuer provides the user with a token. Once the user has that token, it uses it to call your service.
For that, you do not have to reinvent the wheel. Here is JwtAuthForWebAPI nuget package for OAuth2 and OpenId Connect.
It is not secure at all to keep sending username/password with each request, you need to configure your api to issue access tokens for specified life time i.e. 24 hours. To do so you need create and end point (/token) which accepts the username/password validate the combination then issue an access token.
The client which receives this access token is responsible to store is securely and transmit it with each request to an any protected resource using the request "Authorization" header using bearer scheme.
As well you can not do this in one request, you need to obtain the access token at the beginning the you keep calling your protected resources using this access token until it is expired.
You can read more about this in my detailed blog post about Token Based Authentication in Web API

Resources