Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have created a WebApi and a Cordova application. I am using HTTP requests to communicate between the Cordova application and the WebAPI. In the WebAPI, I've implemented OAuth Bearer Token Generation.

public void ConfigureOAuth(IAppBuilder app)
    {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider(new UserService(new Repository<User>(new RabbitApiObjectContext()), new EncryptionService()))
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }

and this is inside the SimpleAuthorizationServerProvider implementation

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
       context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        // A little hack. context.UserName contains the email
        var user = await _userService.GetUserByEmailAndPassword(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "Wrong email or password.");
            return;
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);
    }

after a successful login request to the API from the Cordova app, I receive the following JSON

{"access_token":"some token","token_type":"bearer","expires_in":86399}

The problem is, that I require more information about the user. For example, I have a UserGuid field in the database and I want to send it to the Cordova app when the login is successful and to use it later in other requests. Can I include other information to return to the client, other than "access_token", "token_type" and "expires_in"? If not, how can I get the user in the API based on the access_token?


EDIT:

I think that I found a workaround. I added the following code inside GrantResourceOwnerCredentials

identity.AddClaim(new Claim(ClaimTypes.Name, user.UserGuid.ToString()));

and after that, I access the GUID inside my controller like this: User.Identity.Name

I also can add the the guid with a custom name identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

I'm still interested to know if there is a way to return more data to the client with the bearer token JSON.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
308 views
Welcome To Ask or Share your Answers For Others

1 Answer

You can add as many claims as you want.
You can add the standard set of claims from System.Security.Claims or create your own.
Claims will be encrypted in your token so they will only be accessed from the resource server.

If you want your client to be able to read extended properties of your token you have another option: AuthenticationProperties.

Let's say you want to add something so that your client can have access to. That's the way to go:

var props = new AuthenticationProperties(new Dictionary<string, string>
{
    { 
        "surname", "Smith"
    },
    { 
        "age", "20"
    },
    { 
    "gender", "Male"
    }
});

Now you can create a ticket with the properties you've added above:

var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);

That's the result your client will fetch:

.expires: "Tue, 14 Oct 2014 20:42:52 GMT"
.issued: "Tue, 14 Oct 2014 20:12:52 GMT"
access_token: "blahblahblah"
expires_in: 1799
age: "20"
gender: "Male"
surname: "Smith"
token_type: "bearer"

On the other hand if you add claims you will be able to read them in your resource server in your API controller:

public IHttpActionResult Get()
{
    ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

    return Ok();
}

Your ClaimsPrincipal will contain your new claim's guid which you've added here:

identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

If you want to know more about owin, bearer tokens and web api there's a really good tutorial here and this article will help you to grasp all the concepts behind Authorization Server and Resource Server.

UPDATE:

You can find a working example here. This is a Web Api + Owin self-hosted.
There's no database involved here. The client is a console application (there's a html + JavaScript sample as well) which call a Web Api passing credentials.

As Taiseer suggested, you need to override TokenEndpoint:

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}

Enable 'Multiple Startup Projects' from Solution -> Properties and you can run it straight away.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...