如何在角度http请求中实现client_credentials授权类型?

时间:2017-04-24 18:49:00

标签: c# angularjs asp.net-web-api oauth-2.0

我创建了一个OAUTH2授权服务器,它使用客户端凭据进行身份验证,并负责发布JWT令牌。当我使用邮递员发出请求时,我按预期获得JWT令牌,但当我将请求置于角度时,我收到错误消息:“unsupported_grant_type”。

以下是授权服务器的相关代码:

Startup.cs

public void Configuration(IAppBuilder app)
        {    
            // HTTP Configuration
            HttpConfiguration config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
            ConfigureOAuth(app);
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.UseWebApi(config);
        }

private void ConfigureOAuth(IAppBuilder app)
{
    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        //For Dev enviroment only (on production should be AllowInsecureHttp = false)
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/oauth2/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
        Provider = new CustomOAuthProvider(ActiveKernel),
        AccessTokenFormat = new CustomJwtFormat("http://localhost:62790", ActiveKernel)
    };

    // OAuth 2.0 Bearer Access Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
}

CustomOAuthProvider.cs

public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            Guid clientIdGuid;        

            if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
            {
                context.TryGetFormCredentials(out clientId, out clientSecret);
            }

            if (null == context.ClientId || null == clientSecret  || !Guid.TryParse(clientId, out clientIdGuid))
            {
                context.SetError("invalid_credentials", "A valid client_Id and client_Secret must be provided");
                return Task.FromResult<object>(null);
            }

            // change to async
            var client = _clientRepo.GetClient(clientIdGuid, clientSecret);

            if (client == null)
            {
                context.SetError("invalid_credentials", "A valid client_Id and client_Secret must be provided");
                return Task.FromResult<object>(null);
            }

            context.Validated();
            return Task.FromResult<object>(0);
        }

        public override async Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
        {
            var allowedOrigin = "*";

            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            Guid clientId;
            Guid.TryParse(context.ClientId, out clientId);

            var client = _clientRepo.GetByClientId(clientId);

            if (client == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }

            var identity = new ClaimsIdentity("JWT");
            identity.AddClaim(new Claim("fakeClaim", client.someField.ToString()));

            var props = new AuthenticationProperties(new Dictionary<string, string>
                {
                    {
                         "audience", (context.ClientId == null) ? string.Empty : context.ClientId
                    }
                });

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

当我使用邮递员中的授权类型Oauth2向http://localhost:55555/oauth2/Token发出请求时,我返回了一个有效的JWT令牌,我可以将其添加到我的请求中:

Postman Request

但是,当我尝试使用angular获取访问令牌时,我收到一条错误消息,指出:“unsupported_grant_type”。我想要的grant_type是client_credentials。我已经尝试了多种角度的方法来让这个没有运气。以下是Angular中的当前请求:

    function getLoginToken() {

        var auth = btoa("89C30F1E-DEE3-4C67-8P2E-9C974R5A35EA:B9wXE8Vo+FEkm2AnqFZlS+KJiwYc+bSnarpq90lGyBo=");

        var loginToken = $http({
            url: 'http://localhost:55555/oauth2/Token',
            method: "POST",
            data: {
                grant_type: 'client_credentials'
            },
            withCredentials: true,
            headers: {
                "Authorization": "Basic " + auth,
'Content-Type': 'application/x-www-form-urlencoded'
            }
        }).then(function(data) {
            return data;
        }).catch(function (errorResponse) {
            throw errorResponse;
        });
        return loginToken;
    };

我尝试将“Content-Type”:“application / x-www-form-urlencoded”添加到标头中,并将grant_type添加到URL,但结果是相同的。如果我使用邮递员在不使用授权功能的情况下发出请求;但是使用Body'x-www-form-urlencoded'我会收到与角度相同的错误消息。

在angular和second postman示例中,我实际上在ValidateClientAuthentication方法中获取了正确的client_id和client_secret,并验证了上下文。

以下是两个请求的提琴图片:

来自Angular的破碎请求: Broken angular request

工作邮递员要求: Working Postman Request

有关此处可能出现的问题以及我如何解决问题的任何建议?

提前致谢!

2 个答案:

答案 0 :(得分:0)

我通过添加以下代码行解决了这个问题:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
            var payload = $.param({ grant_type: 'client_credentials' });

grant_type现在作为密钥和&#39; client_credentials&#39;是价值。整个请求如下所示:

    function getLoginToken() {

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
            var payload = $.param({ grant_type: 'client_credentials' });

        var auth = btoa("89C30F1E-DEE3-4C67-8P2E-9C974R5A35EA:B9wXE8Vo+FEkm2AnqFZlS+KJiwYc+bSnarpq90lGyBo=");

        var loginToken = $http({
            url: 'http://localhost:55555/oauth2/Token',
            method: "POST",
            data: payload,
            withCredentials: true,
            headers: {
                "Authorization": "Basic " + auth,
'Content-Type': 'application/x-www-form-urlencoded'
            }
        }).then(function(data) {
            return data;
        }).catch(function (errorResponse) {
            throw errorResponse;
        });
        return loginToken;
    };

我希望这有助于某人下线!

答案 1 :(得分:0)

更清楚原始请求的最低要求必须是:

内容类型:application / x-www-form-urlencoded

grant_type =密码&安培;用户名= USERNAME&安培;密码= PASSWORD