web-dev-qa-db-ja.com

Angular 5でOIDCクライアントでサイレントリフレッシュが機能しない

Oidc-clientでのサイレンリフレッシュに問題があります。サインインは正常に機能し、トークンを取得できます。ただし、サイレントリフレッシュは起動せず、何も起こりません。トークンの有効期限をチェックするメソッド(authservice.tsのsubscribeeventsのメソッド)をサブスクライブすると、これらのメソッドは起動せず、isLoggedIn()メソッドは、トークンが期限切れです!!!!!

誰かが助けてくれる?

これが私のコードです:

    import { Component, OnInit } from '@angular/core';
import { UserManager } from 'oidc-client';
import { getClientSettings } from '../openIdConnectConfig';
import { AuthService } from '../services/auth.service';

@Component({
  selector: 'app-silentrefresh',
  templateUrl: './silentrefresh.component.html',
  styleUrls: ['./silentrefresh.component.css']
})
export class SilentRefreshComponent implements OnInit {


  constructor(private _authService:AuthService) {

  }

  ngOnInit() {
    this._authService.refreshCallBack();
  }


}

次に、私のauthservice:

import { UserManagerSettings, UserManager, User } from 'oidc-client';
import { Injectable } from '@angular/core';
import { getClientSettings } from '../openIdConnectConfig';

@Injectable()
export class AuthService {

  private _manager = new UserManager(getClientSettings());
  private _user: User = null;

  constructor() {
    this._manager.getUser().then(user => {
      this._user = user;
    });

    this._manager.events.addUserLoaded(user => {
      this._user = user;
    });

    this.subscribeevents();

  }

  public isLoggedIn(): boolean {
    return this._user != null && !this._user.expired;
  }

  public getClaims(): any {
    return this._user.profile;
  }

  public subscribeevents() :void {
    this._manager.events.addSilentRenewError(() => {
      console.log("error SilentRenew");
    });

    this._manager.events.addAccessTokenExpiring(() => {
      console.log("access token expiring");
    });

    this._manager.events.addAccessTokenExpired(() => {
      console.log("access token expired");
    });
  }

  public refreshCallBack(): void
  {
    console.log("start refresh callback");
    this._manager.signinSilentCallback()
      .then(data => {console.log("suucess callback")})
      .catch(err => {
          console.log("err callback");
      });
      console.log("end refresh callback");
  }

  getUser(): any {
    return this._user;
  }

  getName(): any {
    return this._user.profile.name;
  }

  getAuthorizationHeaderValue(): string {
    return `${this._user.token_type} ${this._user.access_token}`;
  }

  startAuthentication(): Promise<void> {
    return this._manager.signinRedirect();
  }

  completeAuthentication(): Promise<void> {
    return this._manager.signinRedirectCallback().then(user => {
        this._user = user;
    });


  }
}

そして私の設定:

import { UserManagerSettings } from "oidc-client";

export function getClientSettings(): UserManagerSettings {
  return {
      authority: 'https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679',
      client_id: '257b6c36-1168-4aac-be93-6f2cd81cec43',
      redirect_uri: 'http://localhost:4200/auth-callback',
      //redirect_uri: 'https://demoazureadconnectangular5.azurewebsites.net/auth-callback',
      post_logout_redirect_uri: 'http://localhost:4200/',
      //post_logout_redirect_uri: 'https://demoazureadconnectangular5.azurewebsites.net/',
      response_type:"id_token",
      scope:"openid profile",
      filterProtocolClaims: true,
      loadUserInfo: true,
      automaticSilentRenew: true,
      silent_redirect_uri: 'http://localhost:4200/assets/silentrefresh',
      metadata: {
        issuer: "https://sts.windows.net/136544d9-038e-4646-afff-10accb370679/",
        authorization_endpoint: "https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679/oauth2/authorize",
        token_endpoint: "https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679/oauth2/token",
        //jwks_uri: "https://login.microsoftonline.com/common/discovery/keys",
        jwks_uri: "http://localhost:4200/assets/keys.json",
        //jwks_uri: "https://demoazureadconnectangular5.azurewebsites.net/assets/keys.json",
        //jwks_uri: "http://localhost:50586/api/keys",
        signingKeys: [{"ApiAccessKey": "NgixniZ0S1JHxo7GPEZYa38OBTxSA98AqJKDX5XqsJ8="}]
    }
  };
}

次のような静的ページも使用しようとしました:

<head>
    <title></title>
</head>
<body>
<script src="oidc-client.min.js"></script>
<script>
    var usermanager = UserManager().signinSilentCallback()
        .catch((err) => {
            console.log(err);
        });
</script>
</body>

どちらも発砲したことはありません

迅速にテストするために、IDトークンの有効期限を10分に設定しました。私はAzure AD Connect(AzureのOpen Id Connect)を使用していますが、MicrosoftはOpen ID Connect標準と完全に互換性があると言っています。

誰かがこれを解決するのを手伝ってくれる?

8
Anthony Giretti

問題は、Azure ADからaccess_tokenを要求せず、id_tokenのみを要求することです。両方のトークンを取得するには、response_typeをid_tokenトークンに設定する必要があります。この変更では、さらにいくつかのパラメーターが必要になります。たとえば、バックエンドのリソース。私はここで同様の質問に答えました。私はまたAngular 5とoidcクライアントを使用しています。 https://stackoverflow.com/a/50922730/8081009 そして、ここでも前にここでお答えします https://github.com/IdentityModel/oidc-client-js/issues/504#issuecomment-400056662 ここにサイレント更新を機能させるために設定する必要があるものです。

includeIdTokenInSilentRenew: true
extraQueryParams: {
      resource: '10282f28-36ed-4257-a853-1bf404996b18'
}
response_type: 'id_token token',
scope: 'openid'
loadUserInfo: false,
automaticSilentRenew: true,
silent_redirect_uri: `${window.location.Origin}/silent-refresh.html`,
metadataUrl: 'https://login.microsoftonline.com/YOUR_TENANT_NAME.onmicrosoft.com/.well-known/openid-configuration',
signingKeys: [
    add here keys from link below
]

https://login.microsoftonline.com/common/discovery/keys

また、サイレント更新を備えたコールバックエンドポイントに別の静的ページを使用しています。これは、ユーザーが気付かないためです。このページは可能な限り最小限に抑えられているため、oidcはサイレント更新に使用している非表示のiframeにアプリケーション全体をロードしませんangular.

<head>
  <title></title>
</head>

<body>
  <script src="assets/oidc-client.min.js"></script>
  <script>
    new Oidc.UserManager().signinSilentCallback()
      .catch((err) => {
        console.log(err);
      });
  </script>
</body>
3
Janne Harju

最も簡単な理由は、IDサーバー構成でリダイレクトURLとしてサイレント更新URLを追加しないことです。

アイデンティティサーバーデータベースでは、クライアントのリダイレクトURLは次のようになります。

redirectUrls: [http://localhost:4200/assets/silentrefresh, http://localhost:4200/auth-callback]
1
Lasal Sethiya

オープンIDコネクトと100%完全に互換性のないAzure広告を使用していますが、ID_tokenのみを受け取り、OIDC-CLIENTはaccess_tokenを必要としません。 MicrosoftライブラリADAL.JSに切り替える必要があります

0
Anthony Giretti
Not sure what oidc-client.js version you are using, this should never have worked.

```
new Oidc.UserManager().signinSilentCallback()
                  .catch((err) => {
                      console.log(err);
                  });
``

Usermanager is in **Oidc** object. 
0
hashbytes

私は使用する代わりに、silentRenwを初期化するためにいくつかの異なるアプローチを使用しました

 automaticSilentRenew: true,

私は明示的にsignInSilent();を呼び出すことにしました。私がautoSilentRenewとしていくつかの問題に直面していた理由:true、期待どおりに機能しなかった。

インターフェースを実装するUserAuthクラスコンストラクターでイベントとメソッドを初期化しました

  constructor(private oidcSettings: CoreApi.Interfaces.Authentication.OpenIDConnectionSettings)
    {
     this.userManager.events.addAccessTokenExpiring(() =>
             {
                this.userManager.signinSilent({scope: oidcSettings.scope, response_type: oidcSettings.response_type})
                        .then((user: Oidc.User) =>
                        {
                            this.handleUser(user);
                        })
                        .catch((error: Error) =>
                        {
                           //Work around to handle to Iframe window timeout errors on browsers
                            this.userManager.getUser()
                                .then((user: Oidc.User) =>
                                {
                                    this.handleUser(user);
                                });
                        });
                });
    }

ここで、handleUserはログインしたユーザーを確認するだけです。

したがって、コンストラクタでsignInSilentプロセスを初期化してからsignInSilent completeを呼び出すと、コールバックが機能する場合があります。

0
Sohan