Adding additional logic to Bearer authorization

后端 未结 3 846
借酒劲吻你
借酒劲吻你 2021-01-30 15:11

I am attempting to implement OWIN bearer token authorization, and based on this article. However, there\'s one additional piece of information I need in bearer token that I don\

3条回答
  •  粉色の甜心
    2021-01-30 15:35

    It seems there's something missing in your code.
    You're not validating your client.

    You should implement ValidateClientAuthentication and check your client's credentials there.

    This is what I do:

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
            string clientId = string.Empty;
            string clientSecret = string.Empty;
    
            if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) 
            {
                context.SetError("invalid_client", "Client credentials could not be retrieved through the Authorization header.");
                context.Rejected();
                return;
            }
    
            ApplicationDatabaseContext dbContext = context.OwinContext.Get();
            ApplicationUserManager userManager = context.OwinContext.GetUserManager();
    
            if (dbContext == null)
            {
                context.SetError("server_error");
                context.Rejected();
                return;
            }
    
            try
            {
                AppClient client = await dbContext
                    .Clients
                    .FirstOrDefaultAsync(clientEntity => clientEntity.Id == clientId);
    
                if (client != null && userManager.PasswordHasher.VerifyHashedPassword(client.ClientSecretHash, clientSecret) == PasswordVerificationResult.Success)
                {
                    // Client has been verified.
                    context.OwinContext.Set("oauth:client", client);
                    context.Validated(clientId);
                }
                else
                {
                    // Client could not be validated.
                    context.SetError("invalid_client", "Client credentials are invalid.");
                    context.Rejected();
                }
            }
            catch (Exception ex)
            {
                string errorMessage = ex.Message;
                context.SetError("server_error");
                context.Rejected();
            }
      }
    

    A good article full of details can be found here.
    A even better explanation can be found in this blog series.

    UPDATE:

    I did some digging and webstuff is right.

    In order to pass errorDescription to the client we need to Rejected before we set the error with SetError:

    context.Rejected();
    context.SetError("invalid_client", "The information provided are not valid !");
    return;
    

    or we can extend it passing a serialized json object in the description:

    context.Rejected();
    context.SetError("invalid_client", Newtonsoft.Json.JsonConvert.SerializeObject(new { result = false, message = "The information provided are not valid !" }));
    return;
    

    With a javascript/jQuery client we could deserialize the text response and read the extended message:

    $.ajax({
        type: 'POST',
        url: '',
        data: { username: 'John', password: 'Smith', grant_type: 'password' },
        dataType: "json",
        contentType: 'application/x-www-form-urlencoded; charset=utf-8',
        xhrFields: {
            withCredentials: true
        },
        headers: {
            'Authorization': 'Basic ' + authorizationBasic
        },  
        error: function (req, status, error) {
                if (req.responseJSON && req.responseJSON.error_description)
                {
                   var error = $.parseJSON(req.responseJSON.error_description);
                        alert(error.message);
                }
        }
    });
    

提交回复
热议问题