如何使用 @azure/msal-angular 获取用户的 AAD 成员资格

Posted

技术标签:

【中文标题】如何使用 @azure/msal-angular 获取用户的 AAD 成员资格【英文标题】:How to get user's AAD memberships with @azure/msal-angular 【发布时间】:2021-02-15 14:27:12 【问题描述】:

我正在使用@azure/msal-angular@0.1.4(用于 Angular 的 Microsoft 身份验证库)在我的 Angular 8 应用程序中启用 AAD 身份验证。到目前为止,我的数据库中只有 1 个名为 emp(id、fname、lname、email)的表,并且我使用 .net core 作为后端。

我确实创建了 2 个应用注册,一个用于我的 SPA,另一个用于我的 API。我已经公开了 API 并将我的 AD 中的用户图委托权限设置为拥有 user.Read 和 user.ReadAll。

我的 msaluser 服务如下所示:

import  Injectable  from '@angular/core';
import * as Msal from 'msal';
import  environment  from 'src/environments/environment';
import  Observable  from 'rxjs';

@Injectable()
export class MsaluserService 

  private accessToken: any;
  public clientApplication: Msal.UserAgentApplication = null;
  public clientMembership: Msal.User = null;
  constructor() 
    this.clientApplication = new Msal.UserAgentApplication(
      environment.uiClienId,
      'https://login.microsoftonline.com/' + environment.tenantId,
      this.authCallback,
      
          storeAuthStateInCookie: true,
      );
  

  public GetAccessToken(): Observable<any> 
    if (sessionStorage.getItem('msal.idtoken') !== undefined && sessionStorage.getItem('msal.idtoken') != null) 
        this.accessToken = sessionStorage.getItem('msal.idtoken');
    
    return this.accessToken;
  

  public authCallback(errorDesc, token, error, tokenType) 
    if (token) 

     else 
        console.log(error + ':' + errorDesc);
    
  

  public getCurrentUserFullName() 
    const user = this.clientApplication.getUser();
    alert(user.name);
  

  public getCurrentUserEmail() 
    const user = this.clientApplication.getUser();
    alert(user.displayableId)
  

  public getCurrentUserGroups() 
    // TO BE FETCHED
    // TO BE FETCHED
    // TO BE FETCHED
  

  public logout() 
    this.clientApplication.logout();
  

我的应用模块如下所示

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';

import  AppRoutingModule  from './app-routing.module';
import  AppComponent  from './app.component';
import  environment  from 'src/environments/environment';
import  MsalModule, MsalInterceptor  from '@azure/msal-angular';
import  HttpClientModule, HttpClient, HTTP_INTERCEPTORS  from '@angular/common/http';
import  MsaluserService  from '../_services/msaluser.service';

export const protectedResourceMap: any =
  [
    [environment.baseUrl, environment.scopeUri]
  ];

@NgModule(
  declarations: [
    AppComponent
  ],
  imports: [
    MsalModule.forRoot(
      clientID: environment.uiClienId,
      authority: 'https://login.microsoftonline.com/' + environment.tenantId,
      protectedResourceMap: protectedResourceMap,
      redirectUri: environment.redirectUrl
    ),
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [
    HttpClient,
    MsaluserService,
     provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true 
  ],
  bootstrap: [AppComponent]
)
export class AppModule  

我的路线有一个canActivate: [MsalGuard]

在我的 component.html 中,我调用了这些服务,一切似乎都运行良好。但是,我试图在我的 msaluser 服务的构造函数中获取所有用户的 AAD 成员资格,以便我可以调用此函数

public getCurrentUserGroups() 
        // TO BE FETCHED
      

从我想要的任何组件中注入 msaluser 服务。您能否告诉我应该在 getCurrentUserGroups() 中编写什么代码,以便我可以获得登录用户的 AAD 成员资格?

你应该知道我的开发环境数组是这样的

export const environment = 
  production: false,
  baseUrl:'http://localhost:5000/',
  scopeUri: ['api://<API_APPLICATION_ID>/<NAME>'],
  tenantId: '<TENANT_ID>',
  uiClienId: '<SPA_APPLICATION_ID>',
  redirectUrl: 'http://localhost:4200'
;

更新

这是我尝试调用的方法,但我收到未经授权的请求,尽管 accessToken 是有效的 JWT 令牌

getCurrentUserGroups(): Observable<any[]> 
      this.httpOptions = 
          headers: new HttpHeaders(
              'Content-Type': 'application/json',
              'Authorization': 'Bearer ' + this.msalService.GetAccessToken()
          )

      ;
      console.log(this.msalService.GetAccessToken());
      return this.http.get('https://graph.microsoft.com/v1.0/users/' + this.msalService.getCurrentUserId() + '/getMemberObjects', this.httpOptions)
          .pipe((response: any) => 
              return response;
          );
    

这是解码令牌的屏幕截图,它确实具有属性[hasgroups],所以我应该能够使用我的 JWT 令牌来查询 Microsoft Graph 并获取安全组..

我使用这个令牌从我的后端存储库(.net 核心)中获取员工信息,如下所示:

getEmployees(): Observable<Emp[]> 
      this.httpOptions = 
          headers: new HttpHeaders(
              'Content-Type': 'application/json',
              'Authorization': 'Bearer ' + this.msalService.GetAccessToken()
          )

      ;

      return this.http.get(this.baseUrl + 'emps/', this.httpOptions)
          .pipe((response: any) => 
              return response;
          );
    

它正在正确地进行身份验证并获取数据。

【问题讨论】:

【参考方案1】:

首先,您的访问令牌用于调用您的 Web API,而不是 Microsoft Graph。

根据您的代码,this.accessToken 似乎是 id 令牌而不是访问令牌。

所以恐怕我们不能直接修改getCurrentUserGroups() 方法来实现您的要求。

如果您想获取用户的 AAD 组,最简单的方法是按照 here 的指示在您的令牌中包含组声明。

您只需修改 Azure AD 应用程序清单中的“groupMembershipClaims”字段:

"groupMembershipClaims": "SecurityGroup"

然后令牌将包含使用所属组的 ID,如下所示:


  "groups": ["group id"]

getCurrentUserGroups() 方法中,尝试使用user.groups 之类的东西。

但您只能在此处获取组 ID。所以可能需要提前通过配置文件关联group id和group name。

事实上,还有另一种更好的方法可以结合组和角色。您可以define some app roles 并将角色分配给组。然后该组中的用户将拥有“角色”声明。

查看另一篇类似的帖子here。

【讨论】:

嗨,艾伦。我尝试将我的两个应用程序注册(SPA 和 API)中的 groupMembershipClaims 更改为这样 "groupMembershipClaims": "SecurityGroup" 但我仍然无法获取组 ID 我的应用程序在链接c-sharpcorner.com/article/…中是这样设置的 还有@Allen,如何在配置文件中关联组id和组名? @Riad 你在使用隐式授权流吗?一个用户有多少个组?如果您使用隐式授权流并且用户拥有 6 个以上的组,则 groups 声明将替换为 hasgroups,在这种情况下您必须调用 Microsoft Graph。见docs.microsoft.com/en-us/azure/active-directory/develop/…。 @Riad "如何在配置文件中关联组id和组名",提前在配置文件中写入组名和对应的组id,然后读取。跨度>

以上是关于如何使用 @azure/msal-angular 获取用户的 AAD 成员资格的主要内容,如果未能解决你的问题,请参考以下文章

“npm install @azure/msal-browser @azure/msal-angular@latest”,但 node_modules 内没有

不记名令牌未添加到 HTTP 请求 - MSAL2 Angular

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]