Search code examples
apisecurityjwtidentityserver4

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


Solution

  • 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.