Apiresource VS APIscope VS Identityresource

ApiResource vs ApiScope vs IdentityResource

Scopes listed under IdentityResources are the scopes that will be included in the ID-token.

ApiScopes is what you ask for as a client and as a user you give consent to.
Optionally, one or more ApiResources can associated with an ApiScope.

The ApiScope and ApiResources controls what is included in the access token. ApiResources points out what the aud claim in the access token will contains.

To summarize, the scopes sent by the client is a list of IdentityResources and ApiScopes.

Sample Image

What is different between Claims used in ApiResource and Scope in IdentityServer4

As per the documentation on ApiResource, the UserClaims in the ApiResource itself will always be included in the access token. If you divide that api in multiple Scope's, the UserClaims listed there will be added onto the UserClaims specified in the ApiResource.

Clarification on Identityserver 4 protecting API scopes with ApiResources

First I recommend that you read my answer here

  • what is the use of ApiResourceClaims table? is this returning user claims with access token?

It contains a list of user claims that will be included in the access token. Meaning, the names of the claims that it will then take from the user database.

  • How do I access this scope from the client?

You need to tie an ApiScope. You ask for a ApiScope that then will include one or more ApiResources.

ApiResources represents the individual API's in your system. So, you have one ApiResource per API. You use the ApiResource name and secret to let individual API authenticate against IdentityServer and login to for example get details about the access token (Token introspection)

I think this picture I have below shows the relations between the various parts:
Sample Image

The client asks for a ApiSCope and that will then create an access token that will give access to one or multiple ApiResources. Each ApiResource might using the userclaims ask for additional user information that you want to have present in the Access token. Perhaps for the authorization step in the API. To determine if the user is really allowed in or not.

ApiResource returns invalid_scope identityserver

You as a client asks for ApiScopes, not ApiResources. One more more ApiResource can point to an ApiScope.

An ApiResource represents an API instance, not a Scope. ApiResources are like clients, but for Apis.

See my answer here for more details about the difference between IdentityResource, ApiResource and ApiScope

What are User Claims in IdentityServer4 API Resources vs. API Scopes

A resource is a concept that can be divided into logical parts (scopes) which may be implementated in various ways. Either way, though this may not be very obvious from the documentation, for IdentityServer one resource has at least one scope.

In order to allow a client to access a resource, the client must be configured which scopes are allowed for that client. In the samples the name of the scope is equal to the name of the resource, but in reality a resource has probably multiple scopes. Please note that a client that is allowed to use one scope only, can access the entire resource (audience), unless the resource (api) filters access, based on the allowed scope (scopes are part of the access token as scope claims).

One feature of IdentityServer is that it is a token provider, e.g. for access tokens and identity tokens.

To start with the last one, there are two types of identity tokens. There is one 'minimal' identity token (contains the 'sub' claim only) that is issued only when requested along with an access token. And there is a 'full' identity token that can be requested by a client at the UserInfo endpoint.

For IdentityServer the user claims are a resource (of identity information). As a side note, the user should be asked for consent before using this information because the user owns this information.

Not all user claims should make it to the Identity Token that is requested at the UserInfo endpoint. In order to determine which claims should, IdentityServer looks at the Identity~ tables. Based on these tables a RequestedClaims collection is available for the UserInfo context that is used to filter the user claims resource.

In other words, when a client is configured to request the 'openid' scope, then only the 'sub' claim is included, adding the 'profile' scope will include the underlying profile claims (if available in the UserClaims table), and configuring the 'email' scope will add the email as well to the Identity Token.

For the access token there is a similar mechanism. Based on the ApiClaims and ApiScopeClaims table a RequestedClaims collection is available for the Authorization context. Take a look at my answer here for more information.

Suppose you want to add the 'name' claim to the access token, then add it to one of the tables. Take a look at my answer here or in fact, the entire thread, for additional information.

Though it is possible with IdentityServer to add all sorts of claims to the access token, you should wonder whether this is the right approach, as explained in this post.

The problem with access token claims is that these claims are used for user authorization. But user claims are typically not meant for user authorization. And you don't want to end up with one super access token, containing all claims.

Taking one step back, IdentityServer is there to configure resource protection and client authorization. A client can connect to a resource (scope) but it's the user that is authorized to access the information: requests from a client are always 'on behalf of the user'. That's why the 'sub' claim is always (in an interactive flow) part of the access token. In addition IdentityServer can be extended to handle user authentication. But, though it is possible in the current design, user authorization is not (or at least no longer) the concern of IdentityServer.

The creators of IdentityServer have been thinking about user authorization in the past and came up with a seperate service for this: the PolicyServer. Taking the authorization claims out of IdentityServer and out of the access token.

So, in order to answer your question, the different tables are used to configure resources, scopes, clients, and filters that are used to build tokens. User claims tell something about the user (identity) and are not in place in an access token.

For user authorization I can recommend a PolicyServer server like implementation, combined with resource-based authorization.


A short summary of the tables:

  • AspNetUserClaims - resource of user information

  • ApiResources - the name of the resource

  • ApiScopes - one-to-many scopes that are part of a resource

  • IdentityResources - actually the scope of identity (e.g. openid profile)

  • IdentityClaims - filters AspNetUserClaims for the identity token

  • ApiClaims - filters AspNetUserClaims for the access token, regardless which scope is requested

  • ApiScopeClaims - filters AspNetUserClaims for the access token, depends on the requested scope

  • ClientClaims - claims that are included for the specific client

  • ClientScopes - the allowed scopes for a client


A client requests scopes. If scopes are omitted then (by specification) all allowed scopes are considered as requested.

An api is part of the resource (audience). Finer grained client authorization (based on scope) is required when a resource has multiple scopes.

User authorization is there to determine what a user is allowed to do: a client can connect to the api, is filtered by scope (e.g. calendar) and the user is authorized to read but not write events.

Though calendar.write and calendar.read can be scopes, it has nothing to do with user authorization. The user can be authorized to read and write, but since the client may be limited (e.g. calendar.read only) the user may have to use seperate clients in order to connect to the resource, e.g. a calendar app has both, an email app calendar.read only.

Identityserver4 ApiResource and IdentityResource with same names

Scope names must be unique.

If you are using the "simplified" way of creating resources - scopes with the same name are implicitly created.

IOW - don't do that ;)



Related Topics



Leave a reply



Submit