Search code examples
asp.net-coreoauth-2.0identityserver4api-authorizationpolicy-server

How can I define policies for my API for two types of access tokens, one with an identity (sub) and one without?


I am using IdentityServer4 via ASPNET Core, and I want users to access my API both by the web browser via their identity (Implicit and Hybrid), and by clients programatically (Client Credentials). I realize all I have to do is add AddIdentityServerAuthentication and I am done. However, that only solves the authentication aspect of this problem, not the authorization.

Authorization:

With ASPNET Core, you can just use Role based auth (or PolicyServer permissions which is similar) but only if you have an identity with role claims, that does not work for client credentials. So that brings us to needing to secure by role, or policies AND by scopes. How can I do this?

  • You cant have multiple policies, if you do, they both must pass.
  • You can't have multiple auth schemes, because my call to AddIdentityServerAuthentication will have to use the same authority, so how would IdentityServer4.AccessTokenValidation/JwtBearer know which you scheme challenge you are trying to pass?
  • Multiple requirements could work, but you need to add extra requirements on the condition that you are dealing with a non-identity access token. How can you detect what type of token you are dealing with? Is it safe to just say "If no sub, this is client creds."
  • Should I scrap this design and force device code flow on my users? Look at az cli it magically opens a browser, and then you can start scripting away to your hearts content. IS4 supports this with ease, especially with verficationUrlComplete

I think I have a working POC, but I am far from happy with it. https://gist.github.com/VictorioBerra/8c333a228c55d86a7c15f7f300284634

It involves basically re-implementing the default scope claim requirement handler and policyservers permission requirement handler. But thats the only way to conditionally apply the requirement handlers based on the token type.


Solution

  • There are at least a couple of ways of how to go around your problem of implementing role based authentication:

    • You might have misunderstood the fact that a client can have role claims in the client_credentials flow.
    • You could even have sub claim if you implemented client_credentials_custom flow and essentially bind a client to a particular user account (think of this as a service account)