Federated security, Single Sign On and security token sharing - wcf

In Single Sign On (SSO) scenario if all applications are running in same domain/company,
Is the same Security Token shared among all applications (relying parties) which get users authenticated from the same common identity provider / Security Token Service? What is the default behavior of any STS?
E.g. User A logs on to application X. After some time, she tries to access the application Y. Since she is already authenticated by the same STS and if the token issued to her is still not expired, she won't have to provide credentials while accessing application Y.
My understanding is that it may be possible if the token contains ALL the claims which would be required by all relying parties / applications. But is it a good practice?
Can token's (which was issued when user logged on to application X) expiry time be extended/reset when user A connects to application Y?

WIF implies ADFS usually,
Yes as long as all RP are using the same STS.
No - in ADFS, each RP has its own claims configuration. So the token produced is different (although you could simply copy the configuration if you wanted).
In WIF, yes. You need to use the "sliding token" mechanism.

Related

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.

OpenId Connect renew access_token in SPA

Trying to implement OpenId Connect in Web Application consisting of following components
Identity Provider
Resource server
Single Page Application acting as Client.
Identity Provider and Resource Server are the same application.
SPA use Password Flow to get access_token and stores into the cookie. Storing access_token into cookie has it's security threads, but's it's a different story.
Problem
access_token issued by IdP is expired after 30 min and SPA needs to renew token without asking users for credentials again.
Solution
IdP returns refresh_token along with access_token. Whenever SPA gets 401 from Resource Server, it sends refresh_token to IdP and get's new access_token back.
Problem
Sending refresh_token to SPA is bad practice.
A Single Page Application (normally implementing Implicit Grant) should not under any circumstances get a Refresh Token. The reason for that is the sensitivity of this piece of information. You can think of it as user credentials since a Refresh Token allows a user to remain authenticated essentially forever. Therefore you cannot have this information in a browser, it must be stored securely.
Suggested solution
When the Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's SSO session has not expired.
I think Silent Authentication is not applicable to Password Flow when IdP and Resource Server is same application. access_token issued by IdP is only piece of information which can be used to authorize against Resource Server/IdP after its expiration, how a client can convince IdP to issue new access_token? (without sending refresh_token)
Found angular-oauth2-oidc library which uses refresh_token to renew access_token.
What is best practice/solution in this case to renew access_token?
technical details
Identity Provider - ASP.NET Core + Openiddict library.
SPA - AngularJs application.
Single page applications must not receive refresh tokens. That has been established rules in OAuth 2.0 and OpenID Connect.
One good option I see here is to use Implicit Flow. This will establish a front channel session from your browser to Identity Provider. With password grant type you do a back-channel call (POST), so you don't get such session.
Usually this is a cookie which points to information about previous logged in status (these are identity provider specifics). With completion of the flow, SPA will receive the access token. As you figured out, it will expire. But once that happens, SPA can trigger another implicit flow, but this time with prompt query parameter.
prompt
Space delimited, case sensitive list of ASCII string values that
specifies whether the Authorization Server prompts the End-User for
reauthentication and consent. The defined values are: none , login, consent and select_account
If you identity provider maintain a long lived session (ex:- few hours or days) or if it maintain a remember me cookie, SPA could use prompt=none making it to skip login step from identity provider. Basically, you are getting browser based SSO behaviour with this.
Using the Resource Owner Password Credentials flow defeats the refresh token storage argument: instead of not being able to store the refresh token in a secure place, the SPA would now have to store the Resource Owner credentials in a secure place (assuming you want to avoid requesting username/password from the user frequently). The Implicit grant was designed for usage with an SPA, so it is better to stick with that.
Further to previous answers, the latest OAuth working group guidance for SPAs no longer recommends use of the implicit flow.
If you have simple, shared domain app (IdP, RS and client on a single domain) then you should consider not using OAuth at all. From the doc:
OAuth and OpenID Connect provide very little benefit in this
deployment scenario, so it is recommended to reconsider whether you
need OAuth or OpenID Connect at all in this case. Session
authentication has the benefit of having fewer moving parts and fewer
attack vectors. OAuth and OpenID Connect were created primarily for
third-party or federated access to APIs, so may not be the best
solution in a same-domain scenario.
If you are using OIDC/OAuth in a SPA, they recommend the auth code flow with PKCE.

Adding additional claims to a token after authentication for additional services

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.

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.