Identity Concepts Demystified With IdentityServer — Part 1

Anup Marwadi
HyperTrends
Published in
7 min readApr 20, 2018

The IdentityServer is a great open-source option for those looking to spin up their own Identity Provider. A bunch of great options exist (Auth0 is my favorite), but costs do add up, and if that’s a factor, the Identity Server is a great alternative and has amazing community behind it.

Through these series of posts, I will try to demystify the concepts related to identity.

This is part 1 of a series of article. Other articles are:

  1. https://medium.com/@anupmarwadi/identity-concepts-demystified-part-2-what-are-openid-clients-fd568dbc1c6d

There seems to be quite a bit of confusion around the various concepts. These articles will serve as a reference point for my developers at HyperTrends Global Inc. as well as help anyone else interested.

Quick Assumptions:

  1. To understand implementation details, you will need to know a little bit more about Identity Server (or at least understand the various tables created). I will not go into details on how to setup the Identity Server using Asp.Net Core nor will I explain how it all ties in with EntityFramework etc. This post purely deals in fundamentals as they pertain to the Identity Server.
  2. You understand the need to have an Identity Server. I will focus on the why, although it will help if you understand why you need it.

With that said, let’s look at the core concepts.

API Resources

If you look at the Identity Server Models (or the underlying tables), you’ll notice a few tables that start with Api***. These are the initial tables we will focus in this article.

Here are the tables:

The API** tables generated by IdentityServer

What is an Api Resource?

Anything that you wish to protect using the Identity Server is considered as an API Resource.

Let’s say you have a Catalog API that provides consumers with Catalog information (or Reference Data Information). This API will be responsible for providing information on countries, state/provinces, regions, currency codes, locales, timezones etc.

This is a great micro-service in itself and should be separated out (especially if you’re building Enterprise architectures) so that you have one place to access all this information from. So, let’s call this a Catalog API.

Now that we have established this API, we need to protect it from unauthorized users. Identity Server needs to know that it needs to protect this API. To do so, we create an API Resource.

That’s literally all there is. An API Resource is something the identity server protects.

You can create an API Resource by passing in a Name, a Display Name and a Description. Voila! You have something you can protect.

An Example of a Catalog API with a name

What is an API Scope?

Think of Scopes as an over-arching definition (or scope) of the things you can do with the API.

The Identity Server will check for incoming requests and validate that the scope being requested matches up with the API’s allowed scopes. If a scope isn’t found, or isn’t assigned to the consumer, an ‘invalid_scope’ error will be returned.

Example: An Orders API may allow different over-arching things, like creating orders, listing orders, refunding orders etc. If you really think about this, you could divide this into scopes say: ‘create orders’ and ‘order admin’.

If someone is granted a ‘orders.create’ scope, they can only create orders. This is very useful for a front-facing e-commerce store. You don’t want it to have any other privileges.

If someone is granted ‘orders.admin’ scope, they will have the ability to create, refund, cancel orders and even send emails to purchasers etc. This scope is useful for back-end Admin interfaces for super-users.

Likewise, for our Catalog API, we have 2 distinct overarching scopes: read-only operations and admin operations. You can essentially define these as API Scopes.

This means that you can grant these to consumers and only allow them to do what is a part of that scope. So if I were to grant a read only access to a consumer, they would not be able to perform admin operations. To allow them to perform admin tasks, I’d have to grant them the admin scope.

So, I can easily create new scopes called: catalog.readonly and catalog.admin that I can potentially distribute to consumers depending on the needs.

Please also note that you can choose to display or hide these scopes on the OpenId Configuration page.

Here are the two scopes I built out for our Catalog API. These scopes have a 1:many relationship with the API Resources.

The API Scopes created for the Catalog API

Emphasize — will emphasize this on the Consent screen (more on this later).I would’ve named this EmphasizeOnConsentScreen to make it more clear.

Required — if set to true, implies that user cannot de-select this option from the consent screen.

ShowInDiscoveryDocument — defaults to ‘true’ and will be shown on discovery document of the Open Id Configuration. Hide if you don’t want people to know about this scope.

So there you are, we have Api Scopes.

What is an API Claim?

An API Claim is a User Claim that will be included in the Access Token.

Imagine a scenario where you wanted to include a user’s rights in the Access token. You can setup Api Claims (one or more) to be included in the Access Token.

Please note that these Claims actually have to exist within the system otherwise they are going to be ignored.

This is an important concept.

Let’s say that we have a permission called ‘delete-countries’ which we need to check for before we delete a country. Even though we have Admin capabilities we have granted at the API level using ‘catalog.admin’ scope, we can still check for a ‘delete-countries’ claim to ensure that the user has delete rights.

In our case, we have a Claim Type of ‘user-rights’ and a claim value of ‘catalog.admin’ we have assigned in addition to the Scope. The scope defines what I can do at an API level. The Claim will define what I can do at a user level.

This means, I can allow catalog.admin access at the api level, but cut-off admin capabilities if I want at user level by removing the claim.

Here is an example of an API Claim that I have created:

An API Claim that identifies the user claims to be sent with this API

This means that when a user requests an Access Token, the ‘trypto.user-rights’ claim(s) will be passed within the access token.

You DO NOT need to set these if you don’t want. You can always request them at the user-info endpoint. In our case, we need these in the access token so that the API policies can validate whether a user has admin access or not, so we’re going to include this.

Here’s how a TOKEN looks (decoded) with these claims:

Access Token With Scope and Claims

From the figure above, you can see that because we requested the API Claims for ‘trypto.user-rights’, we now have the claim values for the user in our access token. Also highlighted is the catalog.admin scope and the audience i.e. the Api Resource ‘trypto.catalogapi’.

Now if I were to remove the requested User Claims from the API Claims table, the decoded access token looks like so:

An Access token with No Claims

Notice that the user claims were not sent out with the access token. This could be useful if you don’t need the claims in the token.

Using API Claims, you can pick and choose specific claims to be passed in the access token vs ones that can be retrieved at the User Info endpoint.

What is an API Scope Claim?

An API Scope Claim is simply a User Claim that can be returned with a given scope.

This allows for more granularity to the API Claims. If you wanted claims to only be returned when specific scopes were requested, you could set them up in the API Scope Claims table. Imagine a scenario where you wanted the Admin’s locale preferences in the access token when catalog.admin scope is requested. You could do that by adding that Claim Type for locale in the API Scope Claims table and be done with it.

What is an API Secret?

An API Secret is simply as secret that you can use to introspect tokens.

I promise you, this one baffled me like no other. I hadn’t really given introspection much thought. This is why the Identity server is so well-designed. Let’s say you have a token and you want to look into it to see the information. Well, you can do that using API Secrets. These are so critical for Reference Tokens (as I will explain in future posts).

Essentially you would take your api name ‘trypto.catalogapi’ and your secret, say ‘secret123’ and base64 encode: ‘trypto.catalogapi:secret123’ and then pass that in the header of the introspection request:

Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(“{0}:{1}”, userName, password)));

POST /connect/introspect
Authorization: Basic {base46TokenHere}
Accept: application/json
Content-Type: application/x-www-form-urlencoded

token={tokenToIntrospectHere}

Introspection will be explained in future posts, but for now, just know that an API Secret would allow you to introspect as needed.

Conclusion

Dayum! This turned out to be a long post. I wanted to delve deep into concepts so that they can be consumed as a whole. Hopefully, this should clarify everything you need to know about API Resources i.e. resources you want to protect using an Identity Server.

More to come soon!

UPDATE: Read Part 2 here!

--

--

Anup Marwadi
HyperTrends

Tech Entrepreneur. Product Builder. Student for Life. CEO - HyperTrends, TicketBlox