5

私はstackoverflowのnoobです。asp.net core identity外部ログイントークンを抽出して保存し、ローカルアイデンティティにクレームを追加

私はデフォルトコアIDテンプレート(ローカルアカウント)を使用してasp.netコアを使用しています。

は、私は彼らがそう

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<IActionResult> Login(LoginInputModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      // This doesn't count login failures towards account lockout 
      // To enable password failures to trigger account lockout, set lockoutOnFailure: true 

      var user = await _userManager.FindByNameAsync(model.Email); 

      await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value")); 

のようにローカルでログインしたときに、ユーザープリンシパルにクレームを追加する方法accertainedていると私は外部ログインから返されたクレームを取得する方法を考え出したが、私は追加する方法を見つけ出すことはできませんこれらのユーザプリンシパルがExternalLoginCallback機能に

public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) 
    { 
     if (remoteError != null) 
     { 
      ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); 
      return View(nameof(Login)); 
     } 

     var info = await _signInManager.GetExternalLoginInfoAsync(); 
     if (info == null) 
     { 
      return RedirectToAction(nameof(Login)); 
     } 
     else { 
      // extract claims from external token here 
     } 

     // assume add claims to user here before cookie gets created?? 

     // Sign in the user with this external login provider if the user already has a login. 
     var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); 
     if (result.Succeeded) 

を作成される前に、私は_signInManager.ExternalLoginSignInAsync機能は、かつての意味でのローカルログイン_signInManager.PasswordSignInAsyncに似た働きと仮定していますそれが呼び出され、クッキーが作成されます。しかし、私は確信していません。

基本的には、ユーザーのログイン方法(ローカルまたは外部)に関係なく作成されるCookieにカスタムクレームを追加する方法と、必要に応じてこれらのクレームをデータベースに保持する方法を理解することです。 。

私はgoogle authと言うユーザーのログイン情報を持っている場合、後でGoogle APIを呼び出したいので、Googleからそのaccess_tokenを保存する必要があります。だから私は作成されるユーザープリンシパルでこのaccess_tokenを含めることができる必要があり、私はクッキーがフロントエンドでも使うことができるクレームを持っていると思います。

これはこの質問の範囲外かもしれませんが、Googleトークンの有効期限が切れたときに、リフレッシュトークンを使用して新しいトークンを取得するか、ユーザーに再ログインさせるようにしたいと思います。

これについての助けがあれば、非常に感謝しています。私は本当にこの問題をstackoverflowに投稿せずにこれを理解しようとしました。私は有用な情報をたくさん持っている多くの記事を読んだが、この特定の質問が求めている答えを提供していない。大変ありがとうございます。

歓声

答えて

4

あなたが実際にアイデンティティのaspnetuserclaimsテーブルを更新await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));を使用しています。

_signInManager.PasswordSignInまたは_signInManager.ExternalLoginSignInAsyncを使用してサインインすると、そのテーブルのクレームが読み込まれ、すべてのリクエストがプリンシパルになるクッキーに追加されます。

おそらく、ログインごとにUserManagerからAddClaimAsyncメソッドを呼び出すことは望ましくありません。ここ

を呼び出すとき(ExternalCallbackとExternalCallbackConfirmationにデフォルトのテンプレートを使用している場合)外部ログインプロバイダに関しては、あなたが主張へのアクセス権を持っている:

var info = await _signInManager.GetExternalLoginInfoAsync(); 

クレームがinfo.Principal.Claimsです。

アクセストークンはデフォルトでは含まれていません。それがあるとき、それは(種類と有効期限と一緒に)ここでは次のようになります。

var accessToken = info.AuthenticationTokens.Single(f => f.Name == "access_token").Value; 
var tokenType = info.AuthenticationTokens.Single(f => f.Name == "token_type").Value; 
var expiryDate = info.AuthenticationTokens.Single(f => f.Name == "expires_at").Value; 

は、アクセストークンがAuthenticationTokensコレクションに含まれるようにするには、あなたがtrueにSaveTokensフラグを設定GoogleAuthenticationミドルウェアを設定しているとき:

 app.UseGoogleAuthentication(new GoogleOptions{ 
      ClientId = "...", 
      ClientSecret = "...", 
      SaveTokens = true 

さて、あなたはクレームプリンシパルを作成するプロセスを「引き継ぐ」する必要がクッキーに行く主張する以上のコントロールを持っているしたい場合。

_signInManager.PasswordSignIn/ExternalLoginSignInAsyncを使用すると、これが実行されます。

ので、例えば、ExternalLoginSignInAsyncのために交換してください:

var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); 

をして:

var user = await this._userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); 
    var claimsPrincipal = await this._signInManager.CreateUserPrincipalAsync(user); 
    ((ClaimsIdentity)claimsPrincipal.Identity).AddClaim(new Claim("accessToken", info.AuthenticationTokens.Single(t => t.Name == "access_token").Value)); 
    await HttpContext.Authentication.SignInAsync("Identity.Application", claimsPrincipal); 

"Identity.Applicationは、" デフォルトのCookie名です。あなたはMainCookieに、たとえば、スタートアップのConfigureServices方法でそれを変更することができます。

 services.Configure<IdentityOptions>(options => { 
      options.Cookies.ApplicationCookie.AuthenticationScheme = "MainCookie"; 
     }); 

あなたはまだAccountControllerでExternalCallbackConfirmationアクションを処理する必要があります。これは上記の例に似ています。

関連する問題