Asp.net mvc 手动授予访问令牌MVC Web API

Asp.net mvc 手动授予访问令牌MVC Web API,asp.net-mvc,model-view-controller,asp.net-web-api,Asp.net Mvc,Model View Controller,Asp.net Web Api,我允许用户从应用程序注册到MVC Web API。该应用程序传递电子邮件,但没有密码。我添加用户并分配一个随机密码,然后将其发送给用户 我不希望应用程序两次调用api来获取令牌。 因此,对于这个请求,我想返回一个oauth令牌,/token端点返回 我正在尝试此操作,但来自此请求的令牌访问被拒绝。 我错过了什么?如果有更好的方法,我们将不胜感激 Web API具有与Web API模板类似的默认配置。没有什么习俗。我想保持这样 ClaimsIdentity identity = n

我允许用户从应用程序注册到MVC Web API。该应用程序传递电子邮件,但没有密码。我添加用户并分配一个随机密码,然后将其发送给用户

我不希望应用程序两次调用api来获取令牌。 因此,对于这个请求,我想返回一个oauth令牌,
/token
端点返回

我正在尝试此操作,但来自此请求的令牌访问被拒绝。 我错过了什么?如果有更好的方法,我们将不胜感激

Web API具有与Web API模板类似的默认配置。没有什么习俗。我想保持这样

        ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
        Claim providerKeyClaim = new Claim(ClaimTypes.Email, model.Email, ClaimValueTypes.String, "DrySignup", "DrySignup");

        ExternalLoginData externalLogin = new ExternalLoginData
        {
            LoginProvider = providerKeyClaim.Issuer,
            ProviderKey = providerKeyClaim.Value,
            UserName = identity.FindFirstValue(ClaimTypes.Email)
        };

        var info = new ExternalLoginInfo()
        {
            DefaultUserName = model.Email,
            Login = new UserLoginInfo(providerKeyClaim.Issuer, externalLogin.ProviderKey)
        };

        result = await UserManager.AddLoginAsync(user.Id, info.Login);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        identity = await UserManager.CreateIdentityAsync(user, OAuthDefaults.AuthenticationType);
        IEnumerable<Claim> claims = externalLogin.GetClaims();
        identity.AddClaims(claims);
        Authentication.SignIn(identity);

        AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        var currentUtc = new Microsoft.Owin.Infrastructure.SystemClock().UtcNow;
        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromDays(365));
        var accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
        Request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);



        // Create the response building a JSON object that mimics exactly the one issued by the default /Token endpoint
        JObject token = new JObject(
            new JProperty("userName", user.UserName),
            new JProperty("userId", user.Id),
            new JProperty("access_token", accessToken),
            new JProperty("token_type", "bearer"),
            new JProperty("expires_in", TimeSpan.FromDays(9999).TotalSeconds.ToString()),
            new JProperty("issued", currentUtc.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'")),
            new JProperty("expires", currentUtc.Add(TimeSpan.FromDays(365)).ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'"))
        );
        return Ok(token);
ClaimsIdentity identity=newclaimsidentity(OAuthDefaults.AuthenticationType);
Claim providerKeyClaim=新索赔(ClaimTypes.Email、model.Email、ClaimValueTypes.String、“干注册”、“干注册”);
ExternalLoginData externalLogin=新的ExternalLoginData
{
LoginProvider=providerKeyClaim.Issuer,
ProviderKey=providerKeyClaim.Value,
用户名=identity.FindFirstValue(ClaimTypes.Email)
};
var info=new ExternalLoginInfo()
{
DefaultUserName=model.Email,
Login=new UserLoginInfo(providerKeyClaim.Issuer,externalLogin.ProviderKey)
};
结果=wait UserManager.AddLoginAsync(user.Id,info.Login);
如果(!result.successed)
{
返回GetErrorResult(结果);
}
identity=await UserManager.CreateIdentityAsync(用户,OAuthDefaults.AuthenticationType);
IEnumerable claims=externalLogin.GetClaims();
身份。添加索赔(索赔);
身份验证。签名(身份);
AuthenticationTicket票证=新的AuthenticationTicket(标识,新的AuthenticationProperties());
var currentUtc=new Microsoft.Owin.Infrastructure.SystemClock().UtcNow;
ticket.Properties.IssuedUtc=currentUtc;
ticket.Properties.ExpiresUtc=currentUtc.Add(TimeSpan.FromDays(365));
var accessToken=Startup.OAuthOptions.AccessTokenFormat.Protect(票证);
Request.Headers.Authorization=new System.Net.Http.Headers.AuthenticationHeaderValue(“Bearer”,accessToken);
//创建响应,构建一个JSON对象,该对象完全模仿默认/令牌端点发出的JSON对象
JObject令牌=新JObject(
新的JProperty(“用户名”,user.userName),
新的JProperty(“userId”,user.Id),
新的JProperty(“访问令牌”,accessToken),
新产权(“令牌类型”、“持有人”),
新的JProperty(“expires_in”,TimeSpan.FromDays(9999.TotalSeconds.ToString()),
新的JProperty(“已发布”,当前UTC.ToString(“ddd,dd-MMM-yyy-HH':'mm':'ss'GMT')),
新的JProperty(“expires”,currentUtc.Add(TimeSpan.FromDays(365)).ToString(“ddd,dd-MMM-yyyy-HH:mm:ss'GMT'))
);
返回Ok(令牌);

您的问题的简短答案是,您不能以这种方式颁发令牌并使用内置的OAuthProvider

通过在
OAuthServerOptions
中将此函数设置为
AuthorizeEndpointPath
,您仍然可以实现所需的功能

如果您这样做,您将不得不发送
response\u type=token&client\u id=something&redirect\u uri=/index.html
query参数作为请求的一部分,然后您将得到一个302,其中访问令牌作为url的一部分。比如:
http://example.com/index.html/#access_token={long token string here}&token_type=bearer&expires_in=1209600

然后在你的控制器函数中,你的代码看起来像这样

ApplicationUser user = await UserManager.FindByEmailAsync("email@example.com");
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);


AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
Authentication.SignIn(properties, oAuthIdentity);

return Ok();
你的第二个选择是实现一个自定义的授权类型。这将允许您调用/token服务并创建帐户。在OAuthProvider类上,您希望覆盖
GranCustomExtension
函数

public override async Task GrantCustomExtension(OAuthGrantCustomExtensionContext context)
        {
            var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
            var email = context.Parameters["Email"];
            var createUser = new ApplicationUser() { UserName = email, Email = email };

            IdentityResult result = await userManager.CreateAsync(createUser, "Som3R@ndomPassword");

            if (!result.Succeeded)
            {
                return;
            }

            ApplicationUser user = await userManager.FindByEmailAsync(email);


            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
              OAuthDefaults.AuthenticationType);

            AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);

            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
        }
公共重写异步任务GrantCustomExtension(OAuthGrantCustomExtensionContext)
{
var userManager=context.OwinContext.GetUserManager();
var email=context.Parameters[“email”];
var createUser=newapplicationuser(){UserName=email,email=email};
IdentityResult result=await userManager.CreateAsync(createUser,“Som3R@ndomPassword");
如果(!result.successed)
{
返回;
}
ApplicationUser user=await userManager.findbyemailsync(电子邮件);
ClaimsIdentity oAuthIdentity=等待用户.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
AuthenticationProperties=ApplicationAuthProvider.CreateProperties(user.UserName);
AuthenticationTicket=新的AuthenticationTicket(OAuthidentitity,属性);
上下文。已验证(票证);
}
然后,您可以使用URL编码的请求表单向/token发送如下内容的请求
grant\u type=create&Email=test3%40example.com
,您的响应将与使用
password
grant\u type
一样有效

ClaimsIdentity oAuthIdentity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);

oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
oAuthIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));

AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());

DateTime currentUtc = DateTime.UtcNow;
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromDays(365));

string accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
Request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);



// Create the response building a JSON object that mimics exactly the one issued by the default /Token endpoint
JObject token = new JObject(
    new JProperty("userName", user.UserName),
    new JProperty("userId", user.Id),
    new JProperty("access_token", accessToken),
    new JProperty("token_type", "bearer"),
    new JProperty("expires_in", TimeSpan.FromDays(365).TotalSeconds.ToString()),
    new JProperty("issued", currentUtc.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'")),
    new JProperty("expires", currentUtc.Add(TimeSpan.FromDays(365)).ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'"))
);

return Ok(token);

谢谢,你救了我一天。最后我做了这件事,这也是我用于外部登录的,我尝试使用OWIN TestServer,正如一些人建议的那样调用令牌端点,但没有用,在一些项目中,它在我的系统中起作用