Azure Active Directory: Acquiring of Tokens

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

When building Distributed Systems in Cloud or On-Prem, you will usually have to deal with token flow. That means, some application or user have to securely enter the system on some specific place. If you have distributed system if is not unusual that some applications in the system do not use authentication and some do use authentication and authorization. When user or application first time enter secured part of the system, it has to obtain security token. Cloud based application usually work with OAuth tokens.
That means, before user or service invokes some other service they need to obtain a token, from some Security Token Service. The most prominent STS in Azure is Azure Active Directory (AAD) service.

Depending if you are application (=service) or user, you might require a different token. In theory there is no any difference in physical construction of the same token. That means even user but also service can be registered as artifacts. By obtaining tokens they will both have to provide their credentials.  This are commonly username and password.

But in AAD, there are few differences. For example AAD admin can set a policy, which requires a user to change the password after some time. If the user is a service, it can be required to change a password, which cannot be done, because the service has now nothing about that. It would simply stop working, because password has expired.

Another difference is that users can be asked to authenticate again after token has expired. Thi should not happen to the service. For this reason AAD provides two tokens.

- Token for services
- Token for users

Both are same OAuth JWT tokens, but they are acquired and organized a slightly different way. To acquire token for service AAD provides you so called secret key, which is typically much longer than password. By generating of the secret key admin can specify how long the key is valid like 1 year, 5 years of forever.

Users are typically authenticated by using their username and password.

How to acquire token with secret key?

If your code is running inside of a service or application, which should securely (authenticated) invoke some other service following has to be done in AAD:

1. Service which is invoking another service must be registered in AAD as application
2. Service which is invoked must also be registered in AAD as application.
3. Service, which will invoke must have delegated permission to invoke another service.
4. Service which is invoking another service must have a secret key.

To obtain the token service, which is invoking another service must provide its ClientID (newly called ApplicationId) and its key, by specifying grant_type=client_credentials.
This grant-Type signals to AAD, that secret key and clientId are provided and not username and password.
Following shows how this request should look like:

POST https://login.microsoftonline.com/16*73/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client-request-id: 8aefb25e-195c-4331-969e-edc4be1b0079
return-client-request-id: true
x-client-SKU: .NET
x-client-Ver: 2.25.0.0
x-client-CPU: x64
x-client-OS: Microsoft Windows NT 6.2.9200.0
Host: login.microsoftonline.com
Content-Length: 190
Expect: 100-continue
Connection: Keep-Alive

resource=http%3A%2F%2Fdaenet%2Fadapter.de&client_id=a9***fa8&client_secret=1y**Rk%3D&grant_type=client_credentials

Interesting part in the request is body part, which contains grant type and credentials.

Following code snippet shows how to correctly create the request body in C#:

var body = $"resource={resourceUrl}&client_id={m_ClientId}&grant_type=client_credentials&client_secret={m_Secret}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");

How to acquire Token with Username and Password?

In a case of username and password authentication of a user request for obtaining of the token looks slightly different.

POST https://login.microsoftonline.com/16*73/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client-request-id: 8aefb25e-195c-4331-969e-edc4be1b0079
return-client-request-id: true
x-client-SKU: .NET
x-client-Ver: 2.25.0.0
x-client-CPU: x64
x-client-OS: Microsoft Windows NT 6.2.9200.0
Host: login.microsoftonline.com
Content-Length: 190
Expect: 100-continue
Connection: Keep-Alive


resource=http%3A%2F%2Fdaenet2Fadapter.de&client_id=a9***fa&grant_type=pasword&userName=damir&password=hopla

As you see, this time grant_type is set to “password”, and request contains username and password.

Following code snippet shows how to correctly create the request body in C#:

var body = $"resource={resourceUrl}&client_id={clientId}&grant_type=password&username={userName}&password={password}";

var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");


Posted Nov 03 2016, 12:03 AM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.