ASP .NET令牌生成

时间:2018-07-19 10:32:53

标签: c# asp.net bearer-token

使用用户名和密码登录时,我会生成令牌。一切都很好。

现在,我正在尝试实施Facebook登录。然后生成令牌,但是当我尝试从[Authorized] Api User.Identity.GetUserId<int>()获取令牌时,我会返回0; 如果我通过/token Api 登录,则一切正常,并且令牌更长。

用户已创建,一切正常。但是,无法在[Authorized] Apis中获得UserId,我通过AuthenticationProperties中的Identity传递了它。

这是我的OAuth类:

 public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    public static void UseOAuthAuthentication(this IAppBuilder app) {

        app.Use(async (context, next) => {
            if (string.IsNullOrWhiteSpace(context.Request.Headers["Authorization"])) {
                if (context.Request.QueryString.HasValue) {
                    var token = context.Request.QueryString.Value
                        .Split('&')
                        .SingleOrDefault(x => x.Contains("authorization"))?.Split('=')[1];
                    if (!string.IsNullOrWhiteSpace(token)) {
                        context.Request.Headers.Add("Authorization", new[] { $"Bearer {token}" });
                    }
                }
            }
            await next.Invoke();
        });

        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.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
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Configure the application for OAuth based flow
        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);


        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        OAuthBearerOptions.Description = OAuthOptions.Description;

        // The provider is the only object we need to redefine. See below for the implementation
        OAuthBearerOptions.Provider = new CustomBearerAuthenticationProvider();
        OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;

        app.UseOAuthBearerAuthentication(OAuthBearerOptions);


    }
}

public class CustomBearerAuthenticationProvider : OAuthBearerAuthenticationProvider {
    // This validates the identity based on the issuer of the claim.
    // The issuer is set in the API endpoint that logs the user in
    public override Task ValidateIdentity(OAuthValidateIdentityContext context) {
        var claims = context.Ticket.Identity.Claims;
        if (!claims.Any() || claims.Any(claim => claim.Type != "FacebookAccessToken")) // modify claim name
            context.Rejected();
        return Task.FromResult<object>(null);
    }
}

这是我的Facebook登录课程:

           if (!ModelState.IsValid) {
            return BadRequest(ModelState);
        }

        if (string.IsNullOrEmpty(model.token)) {
            return BadRequest("No access token");
        }

        var tokenExpirationTimeSpan = TimeSpan.FromDays(300);
        ApplicationUser user = null;
        string username;
        // Get the fb access token and make a graph call to the /me endpoint
        var fbUser = await VerifyFacebookAccessToken(model.token);
        if (fbUser == null) {
            return BadRequest("Invalid OAuth access token");
        }

        UserLoginInfo loginInfo = new UserLoginInfo("Facebook", model.username);
        user = await UserManager.FindByNameAsync(fbUser.email);

        // If user not found, register him with username.
        if (user == null) {
            if (String.IsNullOrEmpty(model.username))
                return BadRequest("unregistered user");

            user = new ApplicationUser { UserName = model.username };

            var result = await UserManager.CreateAsync(user);
            if (result.Succeeded) {
                result = await UserManager.AddLoginAsync(user.Id, loginInfo);
                username = model.username;
                if (!result.Succeeded)
                    return BadRequest("cannot add facebook login");
            }
            else {
                return BadRequest("cannot create user");
            }
        }
        else {
            // existed user.
            username = user.UserName;
        }

        // common process: Facebook claims update, Login token generation
        user = await UserManager.FindByNameAsync(username);

        // Optional: make email address confirmed when user is logged in from Facebook.
        user.Email = fbUser.email;
        user.EmailConfirmed = true;
        await UserManager.UpdateAsync(user);

        // Sign-in the user using the OWIN flow
        var identity = new ClaimsIdentity(OAuthAuthentication.OAuthOptions.AuthenticationType);

        var claims = await UserManager.GetClaimsAsync(user.Id);
        var newClaim = new Claim("FacebookAccessToken", model.token); // For compatibility with ASP.NET MVC AccountController
        var oldClaim = claims.FirstOrDefault(c => c.Type.Equals("FacebookAccessToken"));
        if (oldClaim == null) {
            var claimResult = await UserManager.AddClaimAsync(user.Id, newClaim);
            if (!claimResult.Succeeded)
                return BadRequest("cannot add claims");
        }
        else {
            await UserManager.RemoveClaimAsync(user.Id, oldClaim);
            await UserManager.AddClaimAsync(user.Id, newClaim);
        }
        Dictionary<string, string> properties = new Dictionary<string, string>();
        properties.Add("UserId", user.Id+"");
        properties.Add("UserName", user.UserName+"");
        properties.Add("Role", "user");

        //AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
        AuthenticationProperties authProperties = new AuthenticationProperties(properties);
        var currentUtc = new Microsoft.Owin.Infrastructure.SystemClock().UtcNow;
        authProperties.IssuedUtc = currentUtc;
        authProperties.ExpiresUtc = currentUtc.Add(tokenExpirationTimeSpan);
        AuthenticationTicket ticket = new AuthenticationTicket(identity, authProperties);
        var accesstoken = OAuthAuthentication.OAuthOptions.AccessTokenFormat.Protect(ticket);

        Request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accesstoken);
        Authentication.SignIn(identity);

        // Create the response building a JSON object that mimics exactly the one issued by the default /Token endpoint
        JObject blob = new JObject(
            new JProperty("userName", user.UserName),
            new JProperty("access_token", accesstoken),
            new JProperty("token_type", "bearer"),
            new JProperty("expires_in", tokenExpirationTimeSpan.TotalSeconds.ToString()),
            new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
            new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString()),
            new JProperty("model.token", model.token)
        );
        // Return OK
        return Ok(blob);

我尝试通过以下方式生成AccessToken:

OAuthAuthentication.OAuthOptions.AccessTokenFormat.Protect(ticket);

和:

OAuthAuthentication.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);

这是相同的...比我从/Token api获得的令牌短。

0 个答案:

没有答案