Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

How to Get Jwt Token for Logged On User or Application pool identity user using OAuth 2 from ADFS C#

5.00/5 (3 votes)
13 Mar 2017CPOL2 min read 21.5K   550  
How to generate Jwt security token for Application pool identity or logged on user using OAuth 2 from ADFS

Introduction

In this article, we will learn how to generate Jwt security token for Application pool identity or logged on user using OAuth 2 from ADFS.

Background

If you are interested, please go through Application pool identities. Now a days, keeping user credentials in any config files or any other resource files is a little dangerous. Instead, we can use application pool identity feature.

It's safer than keeping credentials in any form of source.

Refer to this link.

Using the Code

I built and pushed nuget package in the nuget server called “OAuth2 Authorization Provider 1.0.0”, it has all the pre work done.

Nuget package manager command to install package: Install-Package OAuth2.Authorization

All you need to do is place the appropriate ADFS OAuth 2 configurations in the web or app config files and invoke helper functions from the nuget package mentioned above.

For more information about OAuth 2 specifications, please go through this link.

In this article, we use two ways to get JWT token. They are:

  • Adal flow
  • OAuth code flow

Way 1: Using Adal Flow

Config Dependency

XML
<!--Global appSettings-->
<add key="AdfsInstance" value=""/>
<add key="ClientId" value=""/>
<add key="Resource" value=""/>
<add key="RedirectUri" value="http://localhost:56194/redirect"/>

<add key="AdfsAuthorityUrl" value="https://{0}/adfs/ls/{1}" />

Provide the above configuration values in the appSettings section and invoke the below function call which is available in the “OAuth2 Authorization Provider 1.0.0” nuget package.

C++
AdfsAuthorization.GetAdfsOAuthJwtAccessTokenForWinAppUserUsingAdal()

How It Works

Internally, it uses Microsoft.IdentityModel.Clients.ActiveDirectory nuget package to create authenticate context for ADFS. Authentication context requires resource, clientId, redirectUri, adfsInstance and AuthorityUrl parameters to provide the Jwt token for the logged on user.

Complete Code

C++
if (!AdfsConfiguration.IsInitialized) throw new SecurityException
         (Constants.AdfsConfigurationInitilizationExceptionMessage);
if (string.IsNullOrEmpty(AdfsConfiguration.AdfsAuthorityUrl)) 
         throw new SecurityException
         (Constants.AdfsConfigurationAdfsAuthorityUrlInitilizationExceptionMessage);

try
{
     var authenticationContext = new AuthenticationContext
         (string.Format(AdfsConfiguration.AdfsAuthorityUrl, AdfsConfiguration.AdfsInstance, 
          AdfsConfiguration.Resource), false);

     var asyncRequest = authenticationContext.AcquireTokenAsync
         (AdfsConfiguration.Resource, AdfsConfiguration.ClientId, 
          new Uri(AdfsConfiguration.RedirectUri), new PlatformParameters(PromptBehavior.Auto));
     var accessToken = asyncRequest.Result.AccessToken;
     return accessToken;
}
catch (Exception exp)
{
    var additionalInfo = $" additionalInfo : [authenticationContext : 
       {string.Format(AdfsConfiguration.AdfsAuthorityUrl, AdfsConfiguration.AdfsInstance, 
        AdfsConfiguration.Resource)}]";
    throw new SecurityException
       ($"AdfsAuthorization.GetAdfsOAuthJwtAccessTokenForWinAppUserUsingAdal is failed, 
       {additionalInfo}", exp);
}

Way 2: Using OAuth2 Authorization Code Flow

It has two processes:

  • First, we need to get OAuth code from adfs server based on clientId, resource and redirecturi (which is already configured for the application in the ADFS server).
  • After successfully getting Auth code from ADFS, we have to hand over the Auth code again to the ADFS server to provide Jwt token for the concerned ADFS user.

Config Dependency

XML
<!--Global-->
<add key="AdfsInstance" value=""/>
<add key="ClientId" value=""/>
<add key="Resource" value=""/>
<add key="RedirectUri" value="http://localhost:56194/redirect"/>
<add key="AdfsTokenServiceUrl" value="https://{0}/adfs/oauth2/token/"/>

Provide the above configuration in the appSetting section and invoke the below lines of code, you are all done (which is already available in the nuget package).

C++
await AuthorizationManager.GetAdfsOAuthJwtAccessTokenForWinAppUserUsingAuthCodeAsync()

How It Works

To get auth code, you need to make HttpClient request by providing proper ADFS authentication url.

Complete Code

C++
var authUrl = string.Format(AdfsConfiguration.AdfsAuthUrl, AdfsConfiguration.AdfsInstance, 
              AdfsConfiguration.ClientId, AdfsConfiguration.Resource, 
              AdfsConfiguration.UrlEncodedRedirectUri);
    var authCode = "";
    
    try
    {
        do
        {
            var result = await Client.GetAsync(authUrl);
            await result.Content.ReadAsStringAsync();
            IEnumerable<string> values;
            if (result.Headers.TryGetValues("location", out values))
            {
                foreach (string s in values)
                {
                    if (s.Contains("code="))
                    {
                        authUrl = "";
                        authCode = s.Substring(s.IndexOf("code=", StringComparison.Ordinal) + 5);
                    }
                    else
                    {
                        authUrl = s;
                    }
                }
            }
            else
            {
                authUrl = "";
            }
        } while (!string.IsNullOrEmpty(authUrl));
        
        return authCode;
    }
    catch (Exception exp)
    {
        var additionalInfo = $"additionalInfo : [authUrl: {authUrl}]";
        throw new SecurityException
        ($"AdfsAuthorization.GetAuthCodeForWinAppUserAsync is failed, {additionalInfo}", exp);
    }

After getting Authcode, use WebClient to get Jwt token, which is in encrypted format. If you want to see what it contains, then you need to have the appropriate certificate to validate and see what it has. This ability is also available in the nuget.

Complete Code

C++
var client = new WebClient();
    try
    {
        if (AdfsConfiguration.UseProxy == "Y")
        {
            var proxyObject = new WebProxy("Proxy", 80) 
            { Credentials = CredentialCache.DefaultNetworkCredentials };
            client.Proxy = proxyObject;
        }
        
        //Uri address = new Uri(String.Format("https://{0}/adfs/oauth2/token/", AdfsInstance));
        Uri address = new Uri
        (string.Format(AdfsConfiguration.AdfsTokenServiceUrl, AdfsConfiguration.AdfsInstance));
        
        Uri redirectAddress = new Uri(AdfsConfiguration.RedirectUri);
        
        NameValueCollection values = new NameValueCollection
        {
            {"client_id", AdfsConfiguration.ClientId},
            {"grant_type", "authorization_code"},
            {"code", code},
            {"redirect_uri", redirectAddress.ToString()}
        };
        
        byte[] responseBytes = client.UploadValues(address, "POST", values);
        
        string response = System.Text.Encoding.UTF8.GetString(responseBytes);
        
        return response;
        
    }
    catch (Exception exp)
    {
        var additionalInfo = $" additionalInfo : 
        [address: {string.Format(AdfsConfiguration.AdfsTokenServiceUrl, 
        AdfsConfiguration.AdfsInstance) }, redirect Uri :{AdfsConfiguration.RedirectUri}]";
        throw new SecurityException($"AdfsAuthorization.GetAdfsOAuthTokenByAuthCode is failed, 
        {additionalInfo}", exp);
    }
    finally
    {
        client.Dispose();
    }

That’s all to get Jwt token for the logged on or application pool identity from the ADFS server.

Along with this article, I have attached the sample testing tool to play around (Winform - test application).

History

  • Version 1.0.1

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)