這個問題是我以前的一個延續:ASP.Net Identity 2 login using password from SMS - not using two-factor authenticationASP.Net身份2 - 自定義響應從OAuthAuthorizationServerProvider
我已經建立我的自定義OAuthAuthorizationServerProvider支持自定義grant_type。
我的想法是創建grant_type爲sms
,它允許用戶生成一次性訪問代碼,該代碼將在發送帶有grant_type密碼的請求時發送到他的移動電話,然後作爲密碼發送給用戶。
現在生成後,通過SMS存儲和發送密碼我想返回自定義響應,而不是從我的GrantCustomExtension令牌。
public override async Task GrantCustomExtension(OAuthGrantCustomExtensionContext context)
{
const string allowedOrigin = "*";
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] {allowedOrigin});
if (context.GrantType != "sms")
{
context.SetError("invalid_grant", "unsupported grant_type");
return;
}
var userName = context.Parameters.Get("username");
if (userName == null)
{
context.SetError("invalid_grant", "username is required");
return;
}
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindByNameAsync(userName);
if (user == null)
{
context.SetError("invalid_grant", "user not found");
return;
}
var generator = new TotpSecurityStampBasedTokenProvider<ApplicationUser, string>();
await userManager.UpdateSecurityStampAsync(user.Id);
var accessCode = await generator.GenerateAsync("SMS", userManager, user);
var accessCodeExpirationTime = TimeSpan.FromMinutes(5);
var result = await userManager.AddAccessCode(user, accessCode, accessCodeExpirationTime);
if(result.Succeeded)
{
Debug.WriteLine("Login code:"+accessCode);
//here I'll send login code to user phone via SMS
}
//return 200 (OK)
//with content type="application/json; charset=utf-8"
//and custom json content {"message":"code send","expires_in":300}
//skip part below
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "SMS");
var ticket = new AuthenticationTicket(oAuthIdentity, null);
context.Validated(ticket);
}
如何停止生成令牌並從OAuthAuthorizationServerProvider返回自定義響應?
我知道兩種方法:TokenEndpoint
,TokenEndpointResponse
,但我想重寫整個響應,而不僅僅是令牌。
編輯:
現在我用下面的代碼在GrantCustomExtension
創建臨時ClaimsIdentity:
var ci = new ClaimsIdentity();
ci.AddClaim(new Claim("message","send"));
ci.AddClaim(new Claim("expires_in", accessCodeExpirationTime.TotalSeconds.ToString(CultureInfo.InvariantCulture)));
context.Validated(ci);
,我重寫TokenEndpointResponse
:
public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
{
if (context.TokenEndpointRequest.GrantType != "sms") return base.TokenEndpointResponse(context);
//clear response containing temporary token.
HttpContext.Current.Response.SuppressContent = true;
return Task.FromResult<object>(null);
}
這有兩個問題:當撥打context.Validated(ci);
時,我說這是一個有效的用戶,但我想回復通過短信發送訪問代碼的信息。 HttpContext.Current.Response.SuppressContent = true;
清除響應,但我想返回一些內容而不是空的響應。
感謝您的解決方案。我會馬上嘗試。可悲的是'OAuthAuthorizationServerProvider'沒有提供任何簡單的解決方案。我想我不是唯一一個想要做這種混合身份驗證的人。 – Misiu
我試過了,不幸的是它不工作。我已經設置了斷點,我可以確認調試器在'c.Get(「sms_grant:sent」)內部訪問過代碼'但響應沒有變化 - 我仍然得到和以前相同的響應。你可以試試你的代碼嗎?也許它只是需要小修補 –
Misiu
我已經搜索了一下,並通過@Lazy Coder發現了這個答案http://stackoverflow.com/a/36414238/965722他的解決方案需要使用MemoryStream清除響應主體。我已經構建了POC解決方案。我會在下面的問題中發佈它,請看看它。也許有一些值得修復的東西。也請修復你的答案。我想授予您的答案,因爲它指向我的正確軌道,但同時我希望您的答案是完整的工作解決方案。 – Misiu