web-dev-qa-db-fra.com

L'actualisation silencieuse ne fonctionne pas avec le client OIDC dans Angular 5

J'ai un problème avec l'actualisation de Silen avec oidc-client. La connexion fonctionne correctement et je suis en mesure d'acquérir un jeton. Cependant, l'actualisation silencieuse ne se déclenche pas, rien ne se passe et lorsque je m'abonne à des méthodes qui vérifient l'expiration du jeton (méthodes dans subscribeevents dans authservice.ts), ces méthodes ne se déclenchent jamais et la méthode isLoggedIn () renvoie toujours un événement réel si le jeton a expiré!!!!!

Quelqu'un pourrait m'aider?

Voici mon code:

    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();
  }


}

Ensuite, mon 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;
    });


  }
}

Et ma config:

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="}]
    }
  };
}

J'ai également essayé d'utiliser une page statique comme celle-ci:

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

Il n'a jamais tiré non plus

Afin de tester rapidement, j'ai configuré l'expiration du jeton ID à 10 min. J'utilise Azure AD Connect (Open Id Connect dans Azure) et Microsoft dit qu'il est entièrement compatible avec la norme Open ID Connect .... Donc, je ne sais pas si c'est de mon côté ou du côté Azure.

Quelqu'un peut m'aider à résoudre ce problème?

8
Anthony Giretti

Le problème est que vous ne demandez pas access_token à partir d'Azure AD, seulement id_token. Vous devez définir response_type sur le jeton id_token pour obtenir les deux jetons. Cette modification nécessitera également quelques paramètres supplémentaires. Par exemple, ressource pour votre backend. J'ai répondu à une question similaire ici. J'utilise aussi Angular 5 et client oidc. https://stackoverflow.com/a/50922730/8081009 Et je vous réponds ici aussi avant https://github.com/IdentityModel/oidc-client-js/issues/504#issuecomment-400056662 Voici ce que vous devez définir pour que le renouvellement silencieux fonctionne.

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

J'utilise également une page statique différente pour le point de terminaison de rappel avec renouvellement silencieux, car de cette façon, l'utilisateur ne remarquera rien. Cette page est minimale possible, donc oidc ne chargera pas toute angular pour iframe caché ce qu'elle utilise pour un renouvellement silencieux. Il est donc recommandé d'être plus efficace.

<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

La raison la plus simple peut être de ne pas ajouter d'URL de renouvellement silencieuse en tant qu'URL de redirection dans la configuration du serveur d'identité.

Dans votre base de données de serveur d'identité, les URL de redirection pour vos clients doivent être comme ceci

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

J'utilise Azure Ad qui n'est pas entièrement compatible à 100% avec open ID Connect, je viens de recevoir un ID_token et aucun access_token requis par OIDC-CLIENT. Je dois passer à la bibliothèque 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

J'ai utilisé une approche différente pour lancer le silentRenw, au lieu d'utiliser

 automaticSilentRenew: true,

J'ai décidé d'appeler explicitement le signInSilent () ;. La raison pour laquelle je faisais face à certains problèmes était automatiqueSilentRenew: vrai, ne fonctionnait pas comme prévu.

J'ai initialisé l'événement et la méthode dans mon constructeur de classe UserAuth qui implémente mon interface

  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);
                                });
                        });
                });
    }

Où en tant que handleUser, il suffit de rechercher l'utilisateur connecté.

Donc, si vous initialisez le processus signInSilent dans votre constructeur, puis appelez signInSilent complete, c'est-à-dire que le rappel peut fonctionner.

0
Sohan