![](/img/trans.png)
[英]Implementing Claims based authentication in ASP.NET WebApi using VS 2013 and ADFS 2.0
[英]Implementing External Authentication for Mobile App in ASP.NET WebApi 2
我正在嘗試構建一個 API(使用 ASP.NET WebApi),它將被學校項目的本機移動應用程序使用。 (我不關心/開發移動應用程序,這個責任落在另一個成員身上)我現在需要實現基於令牌的 Facebook 登錄。 有很多教程可用於如何為基於瀏覽器的應用程序實現此功能(這非常簡單,而且大部分都是內置的),但我不認為我會遵循這將如何與本機應用程序一起使用。 我不明白的是重定向將如何工作?
根據此鏈接,我的服務器無需專門處理任何事情。 我想我不明白這將如何運作? 來自 Facebook 的代幣將如何處理?
另外,我應該實現令牌處理的哪一部分,我真的找不到關於 WebApi 外部登錄身份驗證的好文檔。
無論如何,如果有人可以向我指出發生的令牌交換的確切流程以及 ASP.NET 默認實現的內容,那將非常有幫助。
此外,對我來說最大的困惑是我不明白 Facebook 返回的令牌將如何處理。
如果這是我應該能夠弄清楚的事情,我很抱歉。 我確實做了很多研究,發現自己淹沒在(相關和不相關)信息中。 我想我什至不知道如何搜索我需要的信息。
我讀過的一些鏈接:
基於聲明和令牌的身份驗證 (ASP.NET Web API)
使用 ASP.NET Web API 2、Owin 和 Identity 的基於令牌的身份驗證
ASP.NET Web API 2 在 AngularJS 應用程序中使用 Facebook 和 Google 進行外部登錄
我不得不為我正在處理的應用程序做幾乎相同的事情。 我也很難找到有關它的信息。 似乎我發現的一切都接近我所需要的,但並不完全是解決方案。 我最終從一堆不同的博客文章、文章等中提取了點點滴滴,並將它們放在一起以使其工作。
我記得您發布的兩個鏈接“基於聲明和令牌的身份驗證”和“ASP.NET Web API 2 在 AngularJS 應用程序中使用 Facebook 和 Google 進行外部登錄”是包含有用信息的鏈接。
我不能給你一個全面的答案,因為我不記得我必須做的所有事情,我什至不明白我當時所做的一切,但我可以給你一個大概的想法。 你走在正確的軌道上。
本質上,我最終使用 Facebook 授予的令牌來確認他們已登錄到他們的 Facebook 帳戶,根據他們的 Facebook 用戶 ID 創建了一個用戶,並授予他們我自己的不記名令牌,他們可以使用該令牌訪問我的 API。
流程如下所示:
最終有很多用於使用 ASP.NET Identity 實現 OAuth 內容的自定義代碼,您包含的那些鏈接向您展示了其中的一些。 希望這些信息能對您有所幫助,對不起,我幫不了什么忙。
我跟着這篇文章。 流程基本是這樣
老實說,我不知道這種方法是否合法......
操作按鈕的代碼應該重定向到:
public async Task<IEnumerable<ExternalLoginDto>> GetExternalLogins(string returnUrl, bool generateState = false)
{
IEnumerable<AuthenticationScheme> loginProviders = await SignInManager.GetExternalAuthenticationSchemesAsync();
var logins = new List<ExternalLoginDto>();
string state;
if (generateState)
{
const int strengthInBits = 256;
state = RandomOAuthStateGenerator.Generate(strengthInBits);
}
else
{
state = null;
}
foreach (AuthenticationScheme authenticationScheme in loginProviders)
{
var routeValues = new
{
provider = authenticationScheme.Name,
response_type = "token",
client_id = Configuration["Jwt:Issuer"],
redirect_uri = $"{Request.Scheme}//{Request.Host}{returnUrl}",
state = state
};
var login = new ExternalLoginDto
{
Name = authenticationScheme.DisplayName,
Url = Url.RouteUrl("ExternalLogin", routeValues),
State = state
};
logins.Add(login);
}
return logins;
}
回調動作的代碼:
[Authorize(AuthenticationSchemes = "Identity.External")]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IActionResult> GetExternalLogin(string provider, string state = null, string client_id = null, string error = null)
{
if (error != null)
{
ThrowBadRequest(error);
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider);
}
string providerKey = User.FindFirstValue(ClaimTypes.NameIdentifier);
var externalLoginInfo = new ExternalLoginInfo(User, User.Identity.AuthenticationType, providerKey, User.Identity.AuthenticationType);
if (externalLoginInfo.LoginProvider != provider)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return new ChallengeResult(provider);
}
var userLoginInfo = new UserLoginInfo(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, externalLoginInfo.ProviderDisplayName);
User user = await UserManager.FindByLoginAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey);
if (client_id != Configuration["Jwt:Issuer"])
{
return Redirect($"/#error=invalid_client_id_{client_id}");
}
if (user != null)
{
return await LoginWithLocalUser(user, state);
}
else
{
string email = null;
string firstName = null;
string lastName = null;
IEnumerable<Claim> claims = externalLoginInfo.Principal.Claims;
if (externalLoginInfo.LoginProvider == "Google")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
firstName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
lastName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;
}
else if (externalLoginInfo.LoginProvider == "Facebook")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
string[] nameParts = claims.First(c => c.Type == ClaimTypes.Name)?.Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
firstName = nameParts?.First();
lastName = nameParts?.Last();
}
//some fallback just in case
firstName ??= externalLoginInfo.Principal.Identity.Name;
lastName ??= externalLoginInfo.Principal.Identity.Name;
user = new User
{
UserName = email,
Email = email,
FirstName = firstName,
LastName = lastName,
EmailConfirmed = true //if the user logs in with Facebook consider the e-mail confirmed
};
IdentityResult userCreationResult = await UserManager.CreateAsync(user);
if (userCreationResult.Succeeded)
{
userCreationResult = await UserManager.AddLoginAsync(user, userLoginInfo);
if (userCreationResult.Succeeded)
{
return await LoginWithLocalUser(user, state);
}
}
string identityErrrors = String.Join(" ", userCreationResult.Errors.Select(ie => ie.Description));
Logger.LogWarning($"Error registering user with external login. Email:{email}, Errors:" + Environment.NewLine + identityErrrors);
return Redirect($"/#error={identityErrrors}");
}
}
private async Task<RedirectResult> LoginWithLocalUser(User user, string state)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
DateTime expirationDate = DateTime.UtcNow.AddDays(365);
string token = user.GenerateJwtToken(Configuration["Jwt:Key"], Configuration["Jwt:Issuer"], expirationDate);
return Redirect($"/#access_token={token}&token_type=bearer&expires_in={(int)(expirationDate - DateTime.UtcNow).TotalSeconds}&state={state}");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.