はまったりひらめいたり…とか…

.Net系プログラムで勉強したこととか嵌ったことについて書いたりします。

AngularとAzureAD認証でログイン機構を簡単に実現したい

最初に

今回使用した環境は下記の通りです。

  • @angular/cli : 6.0.8
  • @angular : 6.0.7

AzureAD認証を支援するJSライブラリ

AzureActiveDirectory認証を支援するJSライブラリとして

MicrosoftからADALというJSライブラリが提供されています。

github.com

マルチテナント型のAzureADB2CはMSALと呼ばれるライブラリを使用するようです。

github.com

ADALのAngularラッパーを取得

Angular使いなので、Angularでadal.jsを使おうと思います。

adal.js自体はnpmでパッケージ提供されていないようです。。。

Angularで使用できるラッパーは提供されているようなのでそいつを使用していきます。

npm install adal-angular4 --save

Angular4と書かれていますが6も対応されています。

Angular6対応版もありますが、Deprecateして4に吸収されているようです。

github.com

(名前、ngx~みたいな形のほうがわかりやすいですよね…)

ServiceをImportしてProvide

まずはInjection宣言されている、AdalSeviceを app.module.ts でProvideします。

import { AdalService } from 'adal-angular4';

・・・

providers: [
    AdalService
],

ADの情報を設定

AdalService.init() に使用するADの情報を食わせる必要があります。

Sampleで指定されているのではTenantとClientIDです。

TenantはADで使用されているドメイン

ClientIDはADに登録されたアプリケーションのApplicationIDを指定します。

handleWindowCallbackでログイン状態の収集

先程ProvideしたAdalServiceを介して認証情報のやり取りを行います。

サービス内の handleWindowCallback() を使用し

サインインされているか~ですとか、Tokenの情報~ですとか

そういった情報が収集されているようです。

ログインされているかの情報は

this._adalService.userInfo.authenticated で確認できるので

ログインされているかを確認し

ログインされていないようであればログインするようにしてみます。

  constructor(
    private _adalService: AdalService,
  ) { }

・・・

ngOnInit() {
    this._adalService.handleWindowCallback();
    if (!this._adalService.userInfo.authenticated) {
        this._adalService.login();
    }
}

このようにしておくと、Componentの初期化と同時に

AD未ログイン状態だった場合は

AzureActiveDirectoryの認証画面にリダイレクトされます。

AdalGuardでComponentの遷移Guard

AdalGuardは、Angularの CanActivate

上記の userInfo.authenticated を使用して

AD未ログインユーザーのRoutingの制限を行うSampleという認識です。

adal-angular4/adal.guard.ts at master · benbaran/adal-angular4 · GitHub

認証されていないユーザーへの移動制限をかけたい場合は

routerの設定のときにAdalGuardを指定するだけでOKといった塩梅です。

ここで認証されていない場合は強制的にリダイレクトかけたりなんだりしたいと思うので

基本的にAdalGuardをそのまま使用することはないかなぁ?と思っています。

今回はLoginComponentからDashboardComponentへの遷移の設定を作ってみます。

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'dashboard', component: DashBoardComponent, canActivate: [AdalGuard] },
  { path: '', component: LoginComponent },
];

今回はAdalGuardをそのまま使用します。

認証がすでに済んでいるものはURL指定で直接遷移できていますが

認証が済んでいないほうはRouterで遷移ができずに

何も表示されていない状態になっています。

f:id:TakasDev:20180630122308g:plain

AD認証のAuthがかかったASP.net WebAPIへのアクセス

adal-angular4が提供する AdalInterceptor

AngularのHTTP_INTERCEPTORを使用して、ヘッダに認証情報を付与します。

adal-angular4/adal.interceptor.ts at master · benbaran/adal-angular4 · GitHub

なので、app.module.ts でInterceptorのInjectionを行えばいい感じです。

providers: [
    AdalService,
    {
        provide: HTTP_INTERCEPTORS,
        useClass: AdalInterceptor,
        multi: true
    }
],

WebAPIを作る

WebAPIはASP.net CoreでAD認証付きのAPIがテンプレートから作れるので

それでサクッと作ってしまいます。

f:id:TakasDev:20180630122458j:plain

F5実行して動作を見てみます。

アクセスするAPIはデフォルトで存在する /api/values のGetにアクセスしてみます。

まずは、RestletClientから、Token情報を付与しない状態でアクセスしてみます。

f:id:TakasDev:20180630122651p:plain

401エラーが返却されました。認証は問題なく動作しているようです。

AdalInterceptorを通してからアクセスした場合を見てみます。

f:id:TakasDev:20180630122744j:plain

横着してConsole出力で済ませています。

f:id:TakasDev:20180630123336p:plain

Networkからも、HeaderのAuthorizationにTokenが使用されているのが確認できます。

先程失敗したRestletClientで、使用されたTokenを使ってみます。

f:id:TakasDev:20180630123527p:plain

通りました。正しいTokenのようです。

まとめ

JSでのActiveDirectory認証はADALを使用します。

今回はAngularを使用しましたがVue用等

各Frameworkのものも用意されているようです。

ログイン画面やアカウント管理は非常に重要で気も使う部分です。

簡易な要望でADを使用している人や会社が対象であれば

AD認証で認証ロジックを丸投げしてしまうのもありですよね。