Adding additional claims to a token after authentication for additional services - authentication

Imagine a scenario where a desktop application calls a Single Sign On service to log the current user in. This service authenticates the user and returns a token (a Json Web Token) which is signed with the private part of a public/private key pair. This token has some claims about the identity of the user.
The application then wishes to call a different service for some data and so passes on the token to the service. The service uses the claims in the token (and the fact that it was signed by the SSO service) to identify the current user and to determine which data to return. So far so good.
Now say the application wants to provide some additional pieces of information which are not related to the identity of the user but some context about the current session the user is using in the application (like the current database they are connected to).
These seem like good candidates for additional claims which can be sent with the request, so the data service can extract the claims from the token and use both the identity claims from the SSO and the application specific claims from the desktop application to decide what to do and how to do it. (like which database to update)
The issue is that we can't add claims to the existing token as this has been signed by the SSO service and the application can't know the private key to sign the new token. If the original token is not present then the data service can't trust that the identity came from the SSO, so can't allow access to the data at all.
Options I can think of:
After authentication the application calls the SSO service again providing a collection of claims (secured in some way, not just anyone can call the SSO to get additional claims added to the token) and the SSO token, and the SSO service returns a new token which contains the identity claims and the additional claims the application wants to add
The application creates a new token which it signs and one of the claims in this token is to original token the SSO service provided.
Both of these have pros and cons, but on balance I think I prefer the first option.
To complicate things a little more, there is not just one 'application' there are a few. All will use the same SSO service, and all will want to add some additional application specific claims (ie the claims for app1 and app2 will be different)
Is there an out of the box solution for this problem already? Or are there other ways of dealing with this issue then the options outlined above?

Not sure I like either option.
After authentication the application calls the SSO service again
providing a collection of claims and the SSO token, and the SSO
service returns a new token which contains the identity claims and the
additional claims the application wants to add
I don't think any SSO service will allow you to do this. The claims in the token are signed as the SSO service guarantees they are correct. If the SSO service would start signing arbitrary data, that guarantee no longer holds.
The application creates a new token which it signs and one of the
claims in this token is to original token the SSO service provided.
If you let your application sign access tokens, you'll have to distribute the public keys of both the SSO service and the application. And your data service now has to trust both.
Why not just pass this extra info the data service may need as parameters in the service call? If you are calling the service over HTTPS, the integrity of whatever you pass is guaranteed.

Related

Who generates JWT when using Google OpenID Connect authnentication for my ASP.NET Core Web API app?

I am building an ASP.NET Core 6 Web API application for mobile clients (and maybe later SPA JS app). The application should have sign-in with Google option. I also want to add my own app's custom sign up and sign in options that would also be based on JWT authentication and not cookie.
I understand that for my custom sign in flow my app will generated JWT that will be sent to the client.
But I have few questions how that works when user signs-in with its Google account:
who's responsibility is to generate the JWT when user signs-in with its Google account? Is that responsibility of Google or mine application? I don't want Google to return JWT to the client in the cookie.
Then when client is authenticated with Google, and sends requests to my application, how can my application validate JWT token it gets?
When user signs in with Google for the first time, should I automatically register that user in my application (I am using Identity framework) by taking claim values (email) from the JWT? What is the general practice here?
I am trying to understand these processes and flows so sample code is not necessary (but I do welcome it).
Ad.1. Normally, in a larger system, you would have an authorization server (AS) that would handle user authentication and the issuance of tokens. Your clients would contact only the AS, and the AS will be able to provide the user with different forms of authentication: e.g., through your website's password or through Google. The AS is the single point of issuing tokens to your clients. It can issue tokens regardless of the authentication method used. So it then doesn't matter whether the user authenticated with Google or a password, the client will still get the same access token.
Ad.2. When the AS issues token to your client, then you don't have any problems validating that token. The client doesn't care if the user authenticated with Google or not, it's not relevant in this case.
If you decide to skip using an AS and let the client receive tokens directly from Google, then you can still verify them. An ID token is a JWT and can be easily validated with a JWT library using verification keys provided by Google. Access tokens returned by Google are opaque tokens (If I remember correctly), and you need to check whether Google exposes an endpoint to verify them.
Ad.3. That is the general practice. When the user authenticates with Google and you notice that you don't have that user's data in your system, then you take the information from Google's ID token and create a user entry in your system.

OAuth authorization flow for private API with Microsoft AD

Our company is using Microsoft AD for user management and authentication, also the authorization is done using the AD groups/roles. In the most 3rd party applications the users can authenticate with their AD accounts.
Now we are developing new applications, which should use an internal API. Therefor we created a new enterprise app in our Microsoft tenant and defined a couple of roles.
On the client side it is the normal flow - users authenticate with their accounts and the client receives the access token it should send to the API. And here is the point where I am not sure what is the best way to implement it.
Since all the users already exist in the AD, there is no need to only use access token to get the user identifier and create/link the user in the internal database - I want to use the AD users and to be able to verify the roles and use them in the services behind the API gateway "as is". But the roles are not stored in the access token, so I assume, I have to request them from Microsoft separately. But also I do not want to request them every time a user sends a request to my API and want to rely on the token the cliends sends to me and which I can verify.
So what is the best way to implement it? Should I create a new Bearer JWT in our own auth service, containing all information I need, and provide it to the client, so that it sends it to me every time? Should client use this token for authorizing the user as well? But it also can request the IDToken from Microsoft? Would our internal token replace IDToken and Access Token? Or should we just use IDToken for requests to the API?
Creating an own token looks like an overhead to me, since we only work with AD users but I also don't want to use IDToken for authorization in the API.
In an OAuth architecture your apps (primarily APIs) accept tokens from the Authorization Server (Azure AD in your case). You then use these tokens to authorize requests for data based on Scopes and Claims. Avoid issuing your own tokens and use AS tokens consistently. It feels like you then need to deal with domain specific claims, which is tricky, and these are the main concerns:
Option 1: Custom Claims in JWT Access Tokens
This requires Azure AD to reach out to your internal API at the time of token issuance. This is the preferred option but it may not be supported - or possible - depending on the provider and hosting infrastructure.
Option 2: Custom Claims via Lookup
Here is some example C# code of mine that shows a technique where you form a custom claims principal in the target API. The extra claims are looked up (typically from a database) when the access token is first received, then cached for future requests with the same access token. It is not ideal but I have had to use it in the past due to vendor limitations.
Confidential Internet Tokens
Be careful when including claims in access tokens to not reveal sensitive data to internet clients, eg web or mobile apps. Aim to use the phantom token pattern if possible, so that you do not reveal any sensitive data. If the Authorization Server does not support issuing reference tokens, then option 2 above may be the least bad option.

identityserver4 protect public api

I am using identity server 4, I followed the tutorial, so I have an api, mvc client, console client, and js client.
I saw this blog too, which is probably close to what I need:
https://medium.com/all-technology-feeds/testing-your-asp-net-core-webapi-secured-with-identityserver4-in-postman-97eee976aa16
what I need is an api, where clients can access data, but first, they need authenticate.
we also have the console client, which is also close to what I need.
The only issue with this examples is that in both cases client knows the secret. But in our case multiple clients should use the same api, and if they all have the same secret, they can log in on behalf of each other, but I don't want to have different secrets.
So what I think I could do is to create an api which takes username and password, and returns the token. But I am not sure if this is the right way to do things? This feels like a resource owner flow, which is not supposed to be used for client facing APIs if I am correct. But in that case, how should I go it?
thanks
It seems that there is some confusion. Allow me to give a short summary. First the terminology:
A user is a human that is using a registered client to access resources.
A client is a piece of software that requests tokens from IdentityServer - either for authenticating a user (requesting an identity token) or for accessing a resource (requesting an access token). A client must be first registered with IdentityServer before it can request tokens.
Resources are something you want to protect with IdentityServer - either identity data of your users, or APIs.
Client credentials: The simplest grant type and is used for server to server communication - tokens are always requested on behalf of a client, not a user.
Now about authentication. The client requests tokens at the IdentityServer endpoint. When you use a client in combination with the client credentials flow, then you'll need a clientid + secret. Where secret is really secret and should be known to the client only. You can't use the same secret here. Seems logical when compared to users, they don't share the same password either.
This is close to the resource owner flow, however a client cannot login as a user. For that you'll need another flow, like the hybrid flow. In that case the client logs in on behalf of the user. The difference is the presence of the "sub" claim (the id of the user) in the token.
The client in this case is your app: console or mvc. The first only supports client credentials where the secret is mandatory, the second supports a hybrid flow, where secret may be omitted:
In certain situations, clients need to authenticate with
identityserver, e.g.
confidential applications (aka clients) requesting tokens at the token endpoint
APIs validating reference tokens at the introspection endpoint
The Api is your resource, that you want to protect. The Api never authenticates a user or client. This is done by IdentityServer. It only verifies the token (using the IdentityServer4.AccessTokenValidation package). For that it has its own secret that should only be known to the Api.
In order to grant the client access to the resource you'll need to add the scope to the client in the configuration of IdentityServer. The client is then allowed, not required, to request a token that grants access to the resource.
Again, the Api has nothing to do with authentication. It is also not bound to one client. Multiple clients can access the resource. All you have to do is add the scope to each client that should have access to the resource.
So there is really nothing against it that clients and resources know their secret. You don't have to change anything. All you have to do is choose the appropriate flow.

Authenticate to STS by Issued Token

I'm working on federating an application with various areas and extremely fine-grained permissions. Each of the various areas has a federated WCF endpoint to communicate back to the server. Because of the fine grained permissions, a single token containing all of the permissions can be as large as 1MB, maybe more.
Requirements dictate that the user's username and password credentials must not be held within our code base after the initial log in process. The permissions cannot be combined to create a smaller set. We are using the Thinktecture.IdentityServer for our STS implementation.
My proposed solution is to break each endpoint into its own realm in the STS, and the STS will return a token with the permission claims specified for the realm. To accomplish this I would like to have an Auth realm which is authenticated by username/password and returns a token containing a user, tenant, and subgroup IDs which could then be used as credentials for authenticating to other realms.
Setting up the STS to issue tokens specific to realms has already been implemented. The only requirement remaining is that the username/password is not kept around within our code base.
Is it possible to configure the STS to allow authentication by providing a previously issued token from a specific realm? Is there a better solution which I have not come upon?
Yes, you can authenticate to STS A using a token issued by STS B. STS A has to be configured to trust STS B as a known identity provider.
With thinktecture STS I think you can do this by configuring a new WSStar identity provider. If one realm STS adds the other realm STS as an identity provider, it should begin accepting tokens issued from that realm+certificate.
For WCF, a reasonably painless way to set up issued token channels is with the WIF CreateChannelWithIssuedToken extension method:
http://msdn.microsoft.com/en-us/library/ee517268.aspx
1MB is a very big token indeed. There may be other good reasons to split into multiple STSes in separate realms, but you might alternatively help to solve the problem by dynamically deriving permissions through a policy or permissions stores on the relying party side where your token gets consumed rather than pre-calculating all the granular permissions from the STS side. But I say this without knowing your specific application so feel free to tell me to go away :)
What you really want is re-newing an expired token. We don't support that. And also don't have plans to do that.
You could set the expiration time to a value that works for you - and then force re-login after that.
1 MB tokens are not a good idea - you either need to roundtrip that, or create session affinity. Tokens are meant to describe user identity, not to dump every possible value into them.
Why doesn't the RP load the authZ rules from the IdP via a service call?

Need help understanding WCF Security Architecture

So I've been banging my head against the wall for the past couple days trying to understand how WCF's security architecture worked. I have a goal in mind and I'm not sure that I'm going in the right direction.
The System
We use a combination of Active Directory and databases to manage our authentication and authorization. Client applications typically use their Windows credentials to authenticate and the applications checks against database tables to see if those users are allowed to authenticate and then if they are authorized to use the resources they are requesting. The current setup has each client directly communicating with the database to do these checks.
The Goal
We want to use a Security Token Service to authenticate the client and provide "high level" authorizations for top level resources. The services that provide data or perform actions would operate if the supplied SecurityToken was valid. Additionally, the token, if it did not contain a particular right, would query the token service to see if the user did have rights that were not loaded when the token was initially created. (We have over 300 rights in our database, and that could lead to rather hefty tokens for users with many rights)
What I Don't Understand
1) I understand the token creation process, but I'm a little lost on how the client gets, stores and sends the token to the services it intends to use. Does each "worker" service require a unique token (i.e. call to CalculatorService requires one version of the token and the SaveResultService require a new token to be generated?) Can I manually request, save and send tokens?
2) On the "worker" service side, what is the process by which the token is verified? Does my "worker" service have to contact the Token Service for verification of the token? Or does it just read the token and assume, if it is properly signed, that the token is genuine and operate from that perspective?
3) Is it possible to encrypt my tokens manually and store them on the client side for use while they are valid (thus avoiding authentication attempts on every service call) and so that a web client can save the token between page loads and reuse it on successive calls?
Thanks for helping with my lack of understanding
You should go through the samples for Windows Identity foundation - It providers the classes and implementations required to wrap claims that you can use or query for auth and authz.
http://msdn.microsoft.com/en-us/library/ee517291.aspx
What you are looking for is a durable token cache. - Tokens have lifetimes and usually require renewal and WIF does the renewal under the hood for most scenarios.
You can manually request and attach tokens and pool the proxies using WIF.