Authentication and authorization as a central MicroService ASP.NET - asp.net-web-api

I am planning to change the ASP.NET Web API 2.0 which includes Authentication and Authorization and all the services into Microservices architecture.
My Question if I create a central microservice to handle authentication and authorization. How do I authorize the users sending the request with their tokens to other services?
To elaborate the question:
Let'say I have three microservices.
1 ) ASP NET framework handling authentication and authorization, Which will authenticate a user and sends a token.
2 ) Orders service, Which will receive the requests with the token in their headers. (ASP NET core)
3 ) Accounting service, which will receive the requests with the token in their headers. (ASP NET core)
How do we authorize the users when they call service 2 or 3?
And Is this an ideal approach?

Instead of authenticating external requests at each microservice (you may want to do that for internal microservice communications), I would install a gateway (for example Ocelot which can handle the external "upstream" authentication for you using whatever system you're using, for example for Jwt bearer:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddJwtBearer("TestScheme", x => ...
}
Then in Ocelot you can decide which routes require this scheme as follows
"Routes": [{
"DownstreamHostAndPorts": [...],
"DownstreamPathTemplate": "/",
"UpstreamPathTemplate": "/",
"AuthenticationOptions": {
"AuthenticationProviderKey": "TestScheme", //<--here decide to use this scheme
"AllowedScopes": []
}
}]
If Authentication is successful you can use Ocelot's method of "claims to claims transformation" from your upstream to downstream this method - I personally wanted customise this and build a new Jwt token for internal authentication so used my own downstream handler, like this:
services
.AddHttpClient<IMyService, MyService>(client => ...)
.AddHttpMessageHandler<MyJwtDownstreamHandler>();
//then in the MyJwtDownstreamHandler
request.Headers.Authorization = new AuthenticationHeaderValue(
"bearer",
TokenGenerator.Generate( //<--generate your own Symmetric token using your own method
identity: myIdentity, //<--claims for downstream here
)
);

Based on comments Above
External Identity provider
You may need to use external identity provider e.g. identiyserver4 , azure ad or auth0 etc. Since the token may be generated is JWT token you will have to validate the token.
Validate Token
You need to validate the token in the .Net core Middle ware. Every token issued has a payload and your app middleware will verify every incoming token and reject if it's not able to validate. Your middle ware will fill the claims principle which can be used in your application to validate the authorization as well e.g. roles (if user has authorization to access particular api). You would put "authorize" attribute on top of controller and it will do the job.
You can validate the token manually or some identity provider gives automatic validation e.g. Azure Ad will validate the token and fill the claims principle without doing much effort by simply adding Azure ad nuget package.
There are heaps of example if you simply google. Tokens can be confusing so i would suggest you understand tokens e.g. id_token , access_token , refresh token . Authentication flows and claims. It would become easier if you understand the token types and flows. I am attaching very simple example just to give you idea.
Example

Related

Spring google OAuth2 token validation

I'm developing rest api in spring for my company. I need to secure it using google OAtuh2. Firstly I used jwt token validation. Frontend app obtains token_id andd pass it to backend resource server. I've read that I sholud use access tokens instead of id_tokens (is that right?). For using opaque tokens introspection I need to provide introspection uri. I can't find it. Does google auth server support token introspection?
Yes you should use access-tokens only to secure requests to resource-server(s). ID tokens are for clients to get user-info.
Using access-token introspection has serious performance impact compared to JWT decoding: resource-server must issue a query to authorization-server for each and every request it processes (when JWT validation can be done locally with authorization-server public key retrieved only once). I recomand you don't do that.
If you cannot configure authorization-server to add the claims you need to JWT access-tokens, you should consider using an authorization-server capable of identity federation in front of it. It is very common to do so when several etherogenous identity sources are used (Google + Facebook + Github + LinkedIn + corporate LDAP for instance), but it would work with a single one too. Keycloak for instance does that and allows you to put whatever you need in access-tokens.

Spring boot API with both Oauth 2.0/OpenID Connect and internal authentication?

I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.

Is there any Spring boot Security specific solution to my needs?

I started using spring 4 mounth ago, I want to try any idea that I got and now I want to know if what I m trying to do is possible, if so is there any specific security mechanism that I m not yet aware of.
I successfully implmented a secured API that have Authentication and Authorization using the basic auth and ssl enabled, this API handles a cruds of pizza fabrication with it ingerdiants.
Now I Want to create another API that will handle billing of pizza so this api is going to use the previous.
this reuse principle got my attention is it possible to implement a security mechanisme in my second api that ask my first if my current user is loged in ?
the scenario in my head is looking like
user authentication and authorization in API pizza
user ask api bill to get a bill of a pizza (some request with headers ...)
the bill api asks the pizza api if the request source is already authenticated
pizza api answers if is authenticated or not
bill api store in memory the authentication state
By googling I m not sure if the spring security token based authentication is a solution.
NB: I m using only http Request there is no form or front end
High-level overview of the solution would be as follows:
Establish OAuth2 Server and Zuul gateway.
Service "A" authenticates against OAuth2 authentication server and calls service "B"'s Rest endpoint via Zuul gateway (i.e Zuul proxies call to Service "B") with OAuth2 token stored in the session and adds OAuth2 token in HTTP "Authorization" header on request.
Zuul looks up service "B" endpoint, propagates service "A"'s OAuth2 token using it's filter by inspecting Headers and and forwards call with the same token in "Authorization" header.
Service "B", which is protected resource, receives request, inspects headers and validates recived token against OAuth2 server.
You can also let Zuul automatically propagate OAuth2 access tokens further and authorize incoming requests against the OAuth2 service by using the #EnableOAuth2Sso annotation.

Which information gets sent in each API request using OIDC

I'm writing an API back-end that I want to use OpenID Connect (OIDC) to secure. I've been reading the documentation but I'm still a bit confused what process applies to each and every API request. The Open ID Connect code flow appears to be:
Which I'm fine with, as a one-time process. My back-end API sees an authorization code in the HTTP headers, and sends a request to the authorization server to get the id token. Assuming this validates OK, the data requested is returned in the API response.
But assuming the same user will then be making lots of requests to this API, what happens in subsequent requests? Is there some sort of session created in this mechanism? Do I continue to receive the same authorization code? Do I have to keep sending these back channel requests to the authorization server?
Or should I even output the JWT id token as a cookie? In this way I get the self contained id token coming back in future requests, with no need of a server side session, or further round trips.
I've been reading the documentation but I'm still a bit confused what
process applies to each and every API request
It is not the API that should follow OpenID connect protocol. It's the client that should do it.
My back-end API sees an authorization code in the HTTP headers, and
sends a request to the authorization server to get the id token.
Assuming this validates OK, the data requested is returned in the API
response.
Authorization code must be used by client application and not by the API endpoint. Also, authorization code must never be exposed to other entities.
You should use id token sent with OpenID Connect to authenticate the end user from your client application. To access API, you should use access tokens.
What to do in API endpoint ?
I think this is where you struggle. Your client application should send a valid access token to get access to API endpoint. From API endpoint, you can use OAuth 2.0 introspection endpoint to validate the tokens.
RFC7662 - OAuth 2.0 Token Introspection
This specification defines a protocol that allows authorized
protected resources to query the authorization server to determine
the set of metadata for a given token that was presented to them by
an OAuth 2.0 client.
Note that, OpenID Connect is built on top of OAuth 2.0. This means you can use anything defined in OAuth 2.0, including introspection endpoint. Use this endpoint to verify the access token validity.
What if you want end user details ?
OpenID Connect defines a user info endpoint
User info endpoint
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication. These Claims are normally represented by a JSON object that contains a collection of name and value pairs for the Claims.
Here also, you use access tokens to get user information from this endpoint. The response will let you know the end user to which this token was issued.
Depending on your specific API requirement, you can do a token introspection or obtain user information from user info endpoint. Once that is done you may go ahead and authenticate a session. You might use both endpoints if you need all available information.
Alternatively(instead of sessions) your API can maintain an access token cache. This will remove the need to validate tokens in each an every API call. But be aware that tokens have expiration time. You must consider about token expiration if you are choosing this solution.
p.s - Client vs Resource server
In OpenID Connect and OAuth 2.0 terms, a client could be a simple web page, desktop application or could be even server hosted application.
client
An application making protected resource requests on behalf of the
resource owner and with its authorization. The term "client" does
not imply any particular implementation characteristics (e.g.,
whether the application executes on a server, a desktop, or other
devices).
Obtaining tokens and using them is the duty of the client application.
On the other hand, resource server contains protected resources,
resource server
The server hosting the protected resources, capable of accepting
and responding to protected resource requests using access tokens.
Resource server exchange it's resources to access tokens. If we match the same scenario to basic authentication, access tokens replaces username/password sent with authentication headers.
Typically you'd secure a (pure) API with OAuth 2.0, not OpenID Connect. The Client accessing your API should obtain an OAuth 2.0 access token and in order to do that it may choose to use OpenID Connect to obtain that token. That is all independent of the API, which will only see the access token. The API (or Resource Server in OAuth 2.0 terminology) is not depicted in your diagram.

Authenticating an API request with a Token

Suppose I make an API request to the following URL:
https://myapi.com/data
This is an API I built and have full control over.
I would like to limit access to this API to only the apps I authorize.
I see many services will provide you with an API key which you can append to your URL to give you access.
Suppose I have:
https://myapi.com/data?key=a6reallly7long2string9of0numbers2and4letters
Then on the backend I have something like:
class REST {
public $ACCESS_TOKEN = 'a6reallly7long2string9of0numbers2and4letters',
public function Auth($token){
if($token===$this->ACCESS_TOKEN) return true;
return false;
}
}
If the values match, I allow access.
But all someone would have to do is look at the request the app is making on the client side and they have the token.
Even if I encrypt the token or use one-way hashing, they'll still have the value that decrypts to the correct result.
How does one approach good authentication via URL token for an API?
I would like to limit access to this API to only the apps I authorize.
What are you looking for is "access authorization". Indeed, an access token seems to be a good way, but there are some aspects missing
** Authorization header **
By default the token should be sent as an HTTP header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) not in the url
Commonly used Authorization headers types are Basic (for basic authentication) and Bearer (for OAuth authentication and authorization)
The token should not be a hardcoded constant. It should be created/generated based on the application (and optionally user) authentication. And still better if the token is temporary
Now you can ask - how can an application keep its credentials secret? Each application can have their own server services (end user should.not access application credentials) or pure web application should be comtrolled by the CORS headers
Just search for OAuth 2.0 protocol and JWT token (jwt should be self-contained and signed).
IMHO the URL token may be an option when there is no other alternative, as URL is often cached, resent, logged,...
** API Manager **
If you have resources (server) to do so, you can deploy an API manager (there are open source, commercial or cloud options, just search for some). API manager will handle the application enrollment, authorization and enforcement.

Resources