Identity Server 4 reference token and security - .net-core

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)

Related

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/

Securing a SPA with Spring Boot, OAuth, and JWT?

I've been going through this tutorial which shows how to secure a single page application using several scenarios going from simple to our own Authorization Server that delegates authentication to a provider. The first scenario uses the Authorization Code Grant to log the user in.
Suppose we replace Facebook's OAuth Server with our own in this case and configure it to return a JWT token.
Which OAuth flow should the SPA use if it wants to use the JWT token to secure requests through an edge server that load balances between resources servers?
Also how should spring boot / spring security be configured if we want to use the JWT token to replace the replace the default JSESSION and CSRF support in spring? IIUC the JWT token can be used as a replacement to both of these features.
Update
Based on Manish's answer assuming we are using OAuth 2 implicit flow we:
Put the #EnableResourceServer annotation on the Resource Server
Use an OpenID Connect client to implement the implicity flow
So once this is done are POST request secure assuming each request includes the JWT token as a Bearer Header, or do we need to also configure CSRF?
It will depend on how much your application is sensitive to security but Implicit flow is recommended for pubic client (SPA).
Tutorial is based Authorization Code flow and if you will replace Facebook with your STS, it will still use Authorization Code flow because #EnableOAuth2Sso store the JWT token on server and send the cookie to browser and it also uses refresh token to get the new JWT token. It is a customize flow to implement the Authorization Code flow with public client (SPA) based on API gateway pattern.
To implement the implicit flow - Do not use the #EnableOAuth2Sso at server side, just expose the REST API and secure it with #EnableResourceServer. And you need to use the oidc-client to implement the implicit flow link is here https://github.com/IdentityModel/oidc-client-js
CSRF protection is only required if you will store JWT token or session identifier in the browser's cookie.

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

Apigee: Add login with an existing OAuth 2.0 id-provider

I have an admin-console for an existing service that I want to provide access to by adding login, using our company's OAuth 2.0 service. I want to use Apigee here, so that the web-app with the admin-console does not have to implement the login-logic.
My idea was to use AuthorizationCode flow and let Apigee manage the tokens and I looked into https://github.com/apigee/api-platform-samples/tree/master/sample-proxies/oauth-login-app, but I really can't see how our existing OAuth service fits in.
Is there a sample like that? Perhaps using Google's or Facebook's OAuth service to authenticate the user?
First, Apigee needs to be a proxy into the admin-console. This means that all traffic to the admin-console has to go through Apigee. Otherwise, you won't be able to enforce authentication.
Second, there are a couple different options for integrating with the external oauth 2.0 service. Apigee has the ability to store an external access token and use it as its own, or Apigee can generate a token and store the external access token as a custom attribute.
High level thoughts on how the Apigee proxy could look like:
ProxyEndpoint - endpoint exposed to clients connecting to admin console
TargetEndpoint (not shown in that oauth login-app example) - endpoint for the actual admin console
The flows that execute in the Apigee proxy before sending the request to admin-console will need to implement logic that checks an authentication token. If it's valid, let the request pass onto the TargetEndpoint (admin-console). If the request isn't valid, step through logic that goes calls the external oauth 2.0 server's auth code flow. This will require the following:
Apigee needs to be registered with external oauth 2.0 server.
Logic needs to be built in this proxy to support the redirection based flow of authorization code grant_type (obtaining auth code, receiving the auth code, obtaining token --> all while being redirection based and transparent to user).
In addition to #2, Apigee will need to store the external token as custom attribute and expose the apigee token, or store the external token for verification purposes later on. http://apigee.com/docs/api-services/content/authorize-requests-using-oauth-20 (see Delegating token management). After the token is stored, you'd need to respond with another 302 redirect to the initial uri + token so the request can pass through to admin-console as an authenticated request.
#2 isn't exactly straight-forward and there won't be an example proxy that shows this implementation. If the oauth 2.0 service supported a password grant, it may simplify the implementation, but allows the credentials to pass through apigee and not directly with the authorization server.

Resources