AWS Cognito hosted UI returning id_token in URL - query-string

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/

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.

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)

Proper OAuth2 authentication flow for a web API using the EWS Managed API

I've been reading through a bunch of documentation for using OAuth with Azure AD, but am still completely confused about how to properly implement things for my situation. Hopefully someone can steer me in the right direction.
I have created an ASP.NET Web API application that uses the EWS Managed API to access Exchange on behalf of different users. My application exposes endpoints such as /Mailbox/Messages and /Appointments with the intent that some front end web application will eventually use them to retrieve a user's emails and appointments. Currently the endpoints are working using basic http authentication, but I'd like to update them to use OAuth. The application has been registered in my Azure AD instance and I've configured it to require the "Access mailboxes as the signed-in user via Exchange Web Services" API permission.
Since the front end hasn't been implemented yet, I've been trying to test by manually calling the authentication endpoint. This prompts me to log in and provide consent. If I consent, I'm redirected to the callback URL that I provided when I registered the app with the authorization code contained in the query parameters. I'm still not quite sure how I'm supposed to be using this callback, but for the sake of testing I currently have the callback redeem the authorization code for an access token. This is done by calling the AcquireTokenByAuthorizationCode method on an instance of the AuthenticationContext class and providing my application's id and secret. Again, just for the sake of testing I return the access token to the browser. I can then call my aforementioned endpoints (after some modifications) with this access token and get the emails for the user. I'm guessing much of this is not the correct way to be doing things.
Some of my points of confusion:
What should the callback that I registered in Azure AD actually be doing when it gets the authorization code? Is this intended for a different type of application? Perhaps one that isn't just playing the role of a middle man.
I'm trying to make my application somewhat RESTful, so I don't want to have to maintain the access tokens on my end between requests. As such, does it make sense for my endpoints to expect that the access token be provided in the authentication header for each request? If so, does that mean the front end application should be responsible acquiring the access token and passing it to me?
Being completely new to OAuth and Azure, I'm not sure if any other details are pertinent, but I can provide more information as needed.
What you are implementing is this scenario: https://learn.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api
Here's how it works:
Your client app redirects the user to sign in at the authorization endpoint
Your client app gets back an authorization code (if using the auth code grant flow, there are others)
The client app exchanges the code for an access token for your API app
It will need to provide its client id and secret along with the code and the API's resource URI to get it
The client app calls to your API app, passing the access token in the Authorization header
Your API app then validates the access token, and requests for another access token from Azure AD for the Exchange API
It will pass the access token sent by the client app, along with its client id and secret and the Exchange API's resource URI to Azure AD
Your API app receives an access token so you can call to the Exchange API as the user
And to answer your two questions:
Authorization code flow is not used with APIs, only with apps that have a user signing in, thus the redirect URL is basically never used
Your API can and must expect and authenticate the access token for it to be in every request. But the access token it uses to call the Exchange API can and should be cached on the API's side. This is provided out-of-the-box with ADAL, though the tokens are only in memory.

Requiring the ID token too to access an API endpoint

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

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