How to get access token from Identity Server by passing username and password?

10,900

Solution 1

The way I've tackled this is to add a client credentials client if there is a configured test client secret, I configure this secret only in the test environments but obviously not in higher environments meaning the client never gets added there.

So either in your appsettings.{appropriate_environment}.settings or via an environment variable set up a client secret, then in your IdentityServer config you can add:

//attempt to get the test client secret
var testClientSecret = configuration["TestClientSecret"];
if (!String.IsNullOrWhiteSpace(testClientSecret))
{
    clients.Add(new Client
    {
        ClientId = "MyTestClient",

        AllowedGrantTypes = GrantTypes.ClientCredentials,

        ClientSecrets =
        {
            new Secret(testClientSecret.Sha256())
        },

        AllowedScopes = { "MyApiScope", "MyOtherApiScope", "etc." }
    });
};

Then I have a Postman collection of tests which first POSTs to:

https://{{idp_base_url}}/connect/token

Using basic auth with username of the test client name and password as the client secret (where {{idp_base_url}} is a postman environment variable containing the IdentityServer host appropriate for the environment).

Then I run a few tests but also store the access token to the API:

//tests...
var tokenData = JSON.parse(responseBody);
//more tests...
postman.setEnvironmentVariable("cc_token", tokenData.access_token);

Subsequent tests in the collection can then run your API tests using this token with a bearer token auth header using the above Postman environment variable:

Postman bearer token

Solution 2

Another way is to use IdentityModel NuGet to get the token. Example:

var client = new HttpClient();
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = $"{IdentityServerUrl}/connect/token",
    ClientId = "THE_CLIENT_ID",
    ClientSecret = IdentityServerPass,
    Scope = "api.read"

}).ConfigureAwait(false);
tokenResponse.HttpResponse.EnsureSuccessStatusCode();

Solution 3

First of all declare a class named Token.

public class Token
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("expires_in")]
    public int ExpiresIn { get; set; }

    [JsonProperty("userName")]
    public string Username { get; set; }

    [JsonProperty(".issued")]
    public string IssuedAt { get; set; }

    [JsonProperty(".expires")]
    public string ExpiresAt { get; set; }
}

In Postman we use username, password and grant_type in POST method to generate the access_token from the baseURl/token uri. To know what url you should use, check in the Startup.Auth.cs file in App_Start Folder.

OAuthOptions = new OAuthAuthorizationServerOptions
{
     TokenEndpointPath = new PathString("/Token"),
     .....
}

The appropriate URL is determined by the string inside the PathString() constructor.

Once you know what url to call, now to get the access token, consider the following code.

var keyValues = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("username", username),
    new KeyValuePair<string, string>("password",password),
    new KeyValuePair<string, string>("grant_type", "password")
};

var request = new HttpRequestMessage(HttpMethod.Post, "baseUrl/Token");

request.Content = new FormUrlEncodedContent(keyValues);

var client = new HttpClient();

var response = await client.SendAsync(request);

var content = await response.Content.ReadAsStringAsync();
var accessTokenVar = JsonConvert.DeserializeObject<AuthenticationToken>(content);

Now the access token can be accessed using the accessTokenVar.

Share:
10,900
Osanda Deshan
Author by

Osanda Deshan

A highly focused Associate Technical Specialist experienced in a variety of automation and engineering positions. Organized, methodical and a keen eye for detail results in solid coding and trustworthy automation scripting. Understanding client requirements and communicating the progress of projects are core values in achieving long lasting business relationships.

Updated on June 04, 2022

Comments

  • Osanda Deshan
    Osanda Deshan almost 2 years

    We are using identity server to generate access token for our web services. We have added swagger also. But the problem we faced is, to generate an access token by using a code snippet for API automation. Is there any automated way to get access token by using the username and password?

    Thank You.