How to send bearer token to views in ASP NET MVC 5?

廉价感情. 提交于 2020-01-05 04:41:31

问题


I have a .NET MVC and WEB API project. I want to call the WEB API controllers from javascript but I didn't find a way to send the token to my views. I want to add the bearer token in Viewbag variable, using the below code:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    //GetBearerToken doesn't exists
    ViewBag.BearerToken = Request.GetOwinContext().GetBearerToken();
}

In _Layout.cshtml, I added the folowing code to set Authorization header for all ajax requests:

<script type="text/javascript">
    window.token = '@Viewbag.BearerToken';

    // Add Authorization header on ajax requests
    if(window.token) {
        (function setAjaxRequestsAuthorizationHeader(token) {
            $.ajaxPrefilter(function onAjaxPrefilter(options) {
                if (!options.beforeSend) {
                    options.beforeSend = function onBeforeSend(xhr) {
                        xhr.setRequestHeader('Authorization', 'Bearer ' + token);
                    }
                }
            });
        }(window.token));
        window.token = null;
    }

</script>

Below is my Startup configuration method:

public void ConfigureAuth(IAppBuilder app)
{

    // Configure the db context, user manager and signin manager to use a single instance per request
    //app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext(AppDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

    // Enable the application to use a cookie to store information for the signed in user
    // and to use a cookie to temporarily store information about a user logging in with a third party login provider
    // Configure the sign in cookie
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
            // Enables the application to validate the security stamp when the user logs in.
            // This is a security feature which is used when you change a password or add an external login to your account.  
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, User, int>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                getUserIdCallback: id => id.GetUserId<int>())
        }
    });
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    PublicClientId = "self";
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthProvider(PublicClientId),
        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        // In production mode set AllowInsecureHttp = false
        AllowInsecureHttp = true
    };

    // Enable the application to use bearer tokens to authenticate users
    app.UseOAuthBearerTokens(OAuthOptions);

    // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
    app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
    app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

}

To get a token I also tried (in the MVC Controller methods):

var token = new ClaimsPrincipal(User.Identity).Claims.FirstOrDefault(x => x.Type == "access_token")?.Value;

But the value of variable token is always null.

I have also inspected all claims values but I didn't find any possible token.

How can I send the token to controller views?

Solved

I solved the problem by doing the following steps:

  1. In Startup.Auth.cs I added the folowing static property:

     public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
    
  2. I have created an extension method for ApplicationUser class:

    public static async Task<ClaimsIdentity> GenerateUserIdentityAsync(this ApplicationUser user, UserManager<ApplicationUser, int> manager, string type)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
        // Genereate Bearer token
        if (manager is ApplicationUserManager && type == DefaultAuthenticationTypes.ApplicationCookie)
        {
            var accessTokenFormat = Startup.OAuthOptions.AccessTokenFormat;
            if (accessTokenFormat != null)
            {
                IDictionary<string, string> data = new Dictionary<string, string>
                {
                    ["userName"] = user.UserName
                };
    
                AuthenticationProperties properties = new AuthenticationProperties(data);
                AuthenticationTicket ticket = new AuthenticationTicket(userIdentity, properties);
    
                var token = accessTokenFormat.Protect(ticket);
                userIdentity.AddClaim(new Claim("Access_Token", token));
            }
        }
        return userIdentity;
    }
    
  3. I modified the method OnActionExecuting to send token to the client:

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (Request.IsAuthenticated)
        {
            var identity = (ClaimsIdentity)User.Identity;
            ViewBag.BearerToken = identity.Claims.FirstOrDefault(x => x.Type == "Access_Token")?.Value;
        }
    }
    
  4. In Startup.Auth.cs use the extension method created at step 2 when creating Identity:

    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
        validateInterval: TimeSpan.FromMinutes(30),
        regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager,
        DefaultAuthenticationTypes.ApplicationCookie),
        getUserIdCallback: id => id.GetUserId<int>())
    

来源:https://stackoverflow.com/questions/48931314/how-to-send-bearer-token-to-views-in-asp-net-mvc-5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!