OAuth2 in Thinktecture IdentityServer v2: Resource Owner Password Flow

IdentityServer v2 supports the OAuth2 “Resource Owner Password Credential Flow” (see the spec for more details).

This flow is for so called “trusted applications”, meaning the user gives his username/password to an application, and this app then requests a token on behalf of that user. This also means that the application could do whatever it wants with those credentials. Hence the term “trusted application”.

Generally this flow is discouraged since it uses the password anti-pattern, but often all what people are looking for is something like “WS-Trust for HTTP”, and this flow in OAuth2 is what comes closest to that.

You (aka the client) basically send two pieces of information to the authorization server:

  • Token request (contains the resource identifier and the corresponding resource owner credential)
  • Client credential (Basic Authentication header containing the credentials of the client)

…and get back a token in return that you can use to access the resource on behalf of the resource owner (== user).

Step 0: Setup IdentityServer
Watch this video to get started. When you download the source directly from github, you will see that all the following configuration entries a pre-created for you. In the release version, the config DB is empty.

Step 1: Configure OAuth2
First you need to enable OAuth2 and the ‘Resource Owner Password Credential Flow’ in IdSrv.

OAuth config

Step 2: Register a resource
Next you need to register a resource. This consists (at a minimum) of a resource identifier and a symmetric signing key that will be used to sign the token. This signing key becomes the shared secret between IdSrv and the resource server.

resource

Step 3: Register a client
The last configuration step is to register a client. The client id and secret will be used to authenticate the token request. Also check the corresponding flows you want to enable for this client.

client

Step 4: Request the token
You can use an arbitrary HTTP client to request a token. This is an example using HttpClient:

var form = new FormUrlEncodedContent(
 
new Dictionary<string, string
>

    {

        { OAuth2Constants.GrantType, OAuth2Constants.Password },

        { OAuth2Constants.UserName, “alice” },

        { OAuth2Constants.Password, “password” },

        { OAuth2Constants.scope, scope }

    });

 

var client = new HttpClient();

client.DefaultRequestHeaders.Authorization =
 
new BasicAuthenticationHeaderValue
(
   
Constants.Credentials
.ClientId,    
   
Constants.Credentials
.ClientSecret);

 

var result = client.PostAsync(new Uri(baseAddress), form).Result;

 

..or you can use the OAuth2Client class from Thinktecture.IdentityModel:

var client = new OAuth2Client(

    new Uri(baseAddress),

    Constants.Credentials.ClientId,

    Constants.Credentials.ClientSecret);

 

var response = client.RequestAccessTokenUserName(

    “alice”,

    “password”,

    scope);

(you can lookup the OAuth endpoint on the Application Integration page in IdSrv – use the token endpoint)

Step 5: Use the token
You then typically put the returned token on an Authorization header and sent it to the resource server. I have examples for this in Thinktecture.IdentityModel.

HTH

This entry was posted in IdentityModel, IdentityServer, WebAPI. Bookmark the permalink.

18 Responses to OAuth2 in Thinktecture IdentityServer v2: Resource Owner Password Flow

  1. Alexey says:

    I’m using IdentityModel 4.5 With Identity Server v2. When trying to get token with OAuth2Client i recieve following response: Message={ “error”: “invalid_client” }
    Client ID and Secret is 100% correct. Certificates too. What might be the reason?

    • Alexey says:

      It’s worth to mention, that Basic HTTP Authentication must be enabled in IIS settings for IdentityServer site if you are using username and password to request token.

  2. No. thats not the case.

  3. Please use the issue tracker on github for identity server questions.

  4. panesofglass says:

    The use of all the constant values greatly obscures what url I’m supposed to use to pass the username and password. What url are you using on IdSrv?

  5. Charles says:

    I’m getting the following error on the response:

    var client = new OAuth2Client(
    new Uri(“https://IdSrv/issue/oauth2/token”),
    “http://localhost:1215/”,
    “mTwev3zbTwResG8ffQmR61p92xBiQWZXW+e7AYjHoD8=”);

    try
    {
    var response = client.RequestAccessTokenUserName(
    username,
    password,
    “”);
    }
    catch (Exception ex)
    {
    Debug.WriteLine(ex);
    }

    The ex.message == “Response status code does not indicate success: 400 (Bad Request).”

    I have set the endpoint to the “token endpoint” which looks right. I can hit the url in a web browser and get the following:

    The requested resource does not support http method ‘GET’.

    So it seems to be correct from the outside looking in. Any ideas how to get past this issue?

    The only thing that didn’t look right was maybe the oath endpoint setup:
    OAuth Client : http://localhost:1215/

    The secret does not seem to save, or it disappears after I hit save, and does not load when I refresh the page. However, my Relying Party : http://localhost:1215/ has the signing key setup.

  6. Froms an IdSrv point of view, the scope is the identifier of the resource you are trying to access (also often called a realm).

  7. Charles says:

    Ok, so I’ve added the realm/scope which matches the resource records. However I am still getting an error. So I’m attached my debugger and I can see where the problem lies.

    So I’m passing in “http://localhost:1215/” the same value used when creating the client, as the scope when getting the response.

    However, when I get into the OAtth2TokenController, specifically the ValidateClient method, it returns a:
    ClaimsRepository.ValidateAndGetClient(
    ClaimsPrincipal.Current.Identity.Name,
    passwordClaim.Value,
    out client);

    It seems to not be splitting the string up correctly, so as it looks for relying parties, it never finds on that is “https”.

    • Charles says:

      Seems its stripped out my comments… let me try again… Here are the values when debugging:

      ClaimsPrincipal.Current.Identity.Name == “https”
      passwordClaim.Value == “//localhost:1215/:mTwev3zbTwResG8ffQmR61p92xBiQWZXW+e7AYjHoD8=”

  8. Charles says:

    Yes… so in the ValidateAndGetClient() method, when I correct the clientId from “https” => “https://localhost:1215/”, and correct clientSecret from “//localhost:1215/:mTwev3zbTwResG8ffQmR61p92xBiQWZXW+e7AYjHoD8=” => “mTwev3zbTwResG8ffQmR61p92xBiQWZXW+e7AYjHoD8=”, then all seems to work fine, and I get a token out on the other side.

    So somewhere my ClaimsPrincipal.Current is not being correctly created. Any ideas?

  9. xaxdrax says:

    Hi all, I need help. I’m getting -> Response status code does not indicate success: 401 (Unauthorized).

    My code is
    var client = new OAuth2Client(
    new Uri(“https://localhost/idsrv/issue/oauth2token”), clientId,secret);
    var response = client.RequestAccessTokenUserName(username, password, “https://localhost”);

    Is the username and password the same one as what I have in IdentityServerUsers? Appreciate the help. Thanks

  10. nwdev says:

    Dominick,
    I’ve been struggling to set the client secret in the OAuth client. The OAuth client has only one flow selected, the Resource Owner Password Flow. No matter what I do, it will not save the secret. I’ve tried manually keying one in and generating one.

    Is there something that I am missing here?

    I’ve been able to fetch a token successfully but my web api rejects it and gives me a 401.

  11. Cristian says:

    Hi, hmm, as I can see the RequestAccessTokenUserName is missing from source.. What happened?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s