Generate token in controller

2019-01-31 09:08发布

问题:

I'm using Owin and ASP.NET Identity to use OAuth tokens for securing my Web API methods. The token subsystem is set up as such:

var oauthOptions = new OAuthAuthorizationServerOptions()
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new SimpleAuthorizationServerProvider(),
    AccessTokenFormat = new TicketDataFormat(app.CreateDataProtector(typeof(OAuthAuthorizationServerMiddleware).Namespace, "Access_Token", "v1")),
    RefreshTokenFormat = new TicketDataFormat(app.CreateDataProtector(typeof(OAuthAuthorizationServerMiddleware).Namespace, "Refresh_Token", "v1")),
    AccessTokenProvider = new AuthenticationTokenProvider(),
    RefreshTokenProvider = new AuthenticationTokenProvider(),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    AllowInsecureHttp = true
};

app.UseOAuthAuthorizationServer(oauthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

It works great for requesting tokens based on username/password and then consuming those tokens. However, since the user is already authenticated when hitting the controller that renders the SPA, I would like to generate the token in my view and pass it on to the Javascript code, instead of having to log in again in the SPA.

So my question is: how do I manually generate my token so I can include it in my SPA view?

回答1:

You can generate access token inside a controller by calling OAuthBearerOptions.AccessTokenFormat.Protect(ticket) and the code will look as the below:

       private JObject GenerateLocalAccessTokenResponse(string userName)
    {

        var tokenExpiration = TimeSpan.FromDays(1);

        ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);

        identity.AddClaim(new Claim(ClaimTypes.Name, userName));

        var props = new AuthenticationProperties()
        {
            IssuedUtc = DateTime.UtcNow,
            ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
        };

        var ticket = new AuthenticationTicket(identity, props);

        var accessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);

        JObject tokenResponse = new JObject(
                                    new JProperty("userName", userName),
                                    new JProperty("access_token", accessToken),
                                    new JProperty("token_type", "bearer"),
                                    new JProperty("expires_in", tokenExpiration.TotalSeconds.ToString()),
                                    new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
                                    new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString())
    );

        return tokenResponse;
    }

And you need to declare you OAuthBearerOptions as static property in class Startup.cs

But if you are looking to implement silent refresh for access token without requesting the user to login again, then you should consider implementing refresh token grant, do not do it like the way you suggested. You can read my detailed blog post on how to generate refresh tokens in SPA built with AngularJS.

Hope this answers your question.