How to use RenewToken method of MSADAL in Angular

2019-08-27 17:08发布

问题:

I am using MS Adal NPM package (https://www.npmjs.com/package/microsoft-adal-angular6) for Angular 6 to get the user Authenticated with Azure AD. I am using Implicit Flow to get the Access token. I have been able to get Access token succesfully, with the following code in the constructor.

if (!this.adalSvc.userInfo) {
   this.adalSvc.login();
 } else {
   const token = this.adalSvc.acquireToken('https://graph.microsoft.com').subscribe((token: string) => {
     localStorage.setItem('authtoken', token);
   });
 }

In the Implicit Flow, only Access Token is returned and this access token has an expiry period of one hour. I need to refresh this token. The documentation page of microsoft-adal-angular6 package mentions about the method RenewToken. However, I cannot see any details of this method and I could also not get any sample code that can show me how to use this method. Could anyone help me with this ?

回答1:

I found a nice explanation in the website https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/authentication/auth-silent-aad about how ADAL creates a hidden IFrame.

The ADAL.js library creates a hidden iframe for OAuth 2.0 implicit grant flow, but it specifies prompt=none so that Azure AD never shows the login page. If user interaction is required because the user needs to log in or grant access to the application, Azure AD will immediately return an error that ADAL.js then reports to your app. At this point your app can show a login button if needed.

The solution was very simple. I had to just write one line of code

this.adalsvc.RenewToken('https://graph.microsoft.com');

The only point to note here is that, since "adalsvc" variable is created in the constructor through injection, you need to create a copy of the adalsvc and store it a global variable of the type MsAdalAngular6Service and then execute RenewToken method on this object. Here is a sample code that I have written. I am executign RenewToken in a button click, but in the real scenario, it could be executed in a non-interactical way.

        import { Component } from '@angular/core';
        import { MsAdalAngular6Service } from 'microsoft-adal-angular6';

        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.css']
        })
        export class AppComponent {
          title = 'app';
          newadalsvc: MsAdalAngular6Service;

          onClickMe() {
           this.getNewToken();
          }

          constructor(private adalSvc: MsAdalAngular6Service) {

             if (!this.adalSvc.userInfo) {
               this.adalSvc.login();
             } else {

              const token = this.adalSvc.acquireToken('https://graph.microsoft.com').subscribe((token: string) => {
               this.newadalsvc = adalSvc;
              alert(token);
              console.log(token);
                 localStorage.setItem('authtoken', token);
                }); 
             }
           }


        getNewToken()
        {
          this.newadalsvc.RenewToken('https://graph.microsoft.com');

//Without calling acquireToken the new token will not be set in the "Local Storage"
this.newadalsvc.acquireToken('https://graph.microsoft.com').subscribe((token) => {
        console.log('Token >>>>>>>>>>>>>>', token);
      });
         }
        }