【问题标题】:Issues with OAuth2 and angular-auth2-oidc Library - PKCE Code FlowOAuth2 和 angular-auth2-oidc 库的问题 - PKCE 代码流
【发布时间】:2021-01-29 03:54:22
【问题描述】:

我是 OAuth2 和 angular-auth2-oidc 库的新手,如果我犯了一些新手错误,请多多包涵。

我想要实现的目标: 用户将单击主页中的登录链接,他将被发送到提供商的站点进行登录,然后使用令牌重定向回主页。

到目前为止的结果: 用户被发送到提供商的站点以登录并成功发送回我的站点的主页,但我没有得到任何令牌。 我在ngOnit()的控制台中输出了一些数据,它们都是null,undefined或false。

ngOnit() 函数内,我还输出了一些事件,我在控制台中得到的事件是token_refresh_error。我没有在我的代码中明确地进行任何令牌刷新,但我仍然收到此错误。

在这篇文章的 错误 子标题下,我添加了有关错误的屏幕截图。

这是我的配置和实现:

这是我的 OAuth2 提供者的 openid 配置:

authorization_endpoint                  "https://DOMAIN_PROVIDER/op/v1/auth"
code_challenge_methods_supported    
    0                                   "plain"
    1                                   "S256"
end_session_endpoint                    "https://DOMAIN_PROVIDER/op/v1/logout"
grant_types_supported   
    0                                    "authorization_code"
id_token_signing_alg_values_supported   
    0                                    "RS256"
issuer                                   "https://DOMAIN_PROVIDER/op"
jwks_uri                                 "https://DOMAIN_PROVIDER/op/v1/keys"
response_modes_supported    
    0                                    "query"
    1                                    "fragment"
    2                                    "form_post"
response_types_supported    
    0                                    "code"
scopes_supported    
    0                                    "openid"
subject_types_supported 
    0                                    "public"
token_endpoint                           "https://DOMAIN_PROVIDER/op/v1/token"
token_endpoint_auth_methods_supported   
    0                                    "client_secret_basic"
    1                                    "client_secret_post"
userinfo_endpoint                        "https://DOMAIN_PROVIDER/op/v1/userinfo"

这是我的实现:

//首页组件

export class HomeComponent implements OnInit {

  private oAuthConfig: AuthConfig;

  constructor(private oAuthService: OAuthService) { }

   ngOnInit() {

     // IN THIS METHOD I'M OUTPUTTING ALOT OF STUFF TO THE CONSOLE TO SEE IF IT IS WORKING

      if (!this.oAuthService.getAccessToken()) {
         this.initOAuthConfig();
         console.log('__________ACCESS-TOKEN IS NOT SET___________');
      } else {
         console.log('___ACCESS-TOKEN IS SET:', this.oAuthService.getAccessToken());
      }

      console.log('_____GRANTED-SCOPE:', this.oAuthService.getGrantedScopes());
      console.log('______IDENTITY-CLAIMS:', this.oAuthService.getIdentityClaims());
      console.log('______HAS-ACCESS-TOKEN?:', this.oAuthService.hasValidAccessToken());
      console.log('_____HAS-ACCESS-TOKEN?:', this.oAuthService.hasValidIdToken());
      
    // HERE I'M OUTPUTTNG THE EVENTS TO SEE WHAT IS GOING ON
    this.oAuthService.events.subscribe((e: OAuthErrorEvent) => {
      if (e.type === 'token_received') {
        this.logger.log('____________TOKEN RECEIVED');
      }
      this.logger.log('______====================EVENT-TYPE:', e.type);
      this.logger.log('______====================EVENT-REASON:', e.reason);
      this.logger.log('______====================EVENT-PARAMS:', e.params);
    });

  
    if (this.oAuthService.hasValidAccessToken()) {
      this.oAuthService.loadUserProfile().then((t) => {
        console.log('----USER-PROFILE:', t);
      });
    } else {
      this.logger.log('----HAS VALID ACCESS TOKEN');
    }

   }

  
   
   private initOAuthConfig(): void {
    this.oAuthConfig = {
      redirectUri: window.location.origin + '/login/oauth2/myapp',
      postLogoutRedirectUri: window.location.origin + '/logout',
      clientId: 'CLIENT-ID',
      scope: 'openid, rrn, profile',
      oidc: true,
      issuer: 'https://DOMAIN_PROVIDER/op',
      responseType: 'code',
      showDebugInformation: true,
      tokenEndpoint: 'DOMAIN_PROVIDER/op/v1/token',
      jwks: {'keys': ['DOMAIN_PROVIDER/op/v1/keys']}
    };

    this.oAuthService.setStorage(sessionStorage);
    this.oAuthService.configure(this.oAuthConfig);
    this.oAuthService.loadDiscoveryDocumentAndTryLogin();

}

//包含登录功能的类

export class HeaderComponent {

    
   constructor(private oAuthService: OAuthService) { }


    public login() {
     this.oAuthService.initCodeFlow();
    }

    public logout() {
      this.oAuthService.logOut();
    }

}



// The html of the header component which contains the login link

    <a (click)="login()" title="Login">
       Login
    </a>

// 错误/错误截图

以下是用户被重定向回主页时控制台中的错误

1) 在此屏幕截图中,值是 null、false 或 undefined,除非加载发现文档:

2) 在以下屏幕截图中,您将看到 EVENT-TYPE 之一是token_refresh_errorEVENT-REASONBAD REQUEST。它试图向https//DOMAIN_PROVIDER/op/v1/token 发出请求,但在de initOAuthConfig() 方法中失败了,我添加了tokenEndPoint 属性。 您还可以看到错误是error: "invalid_grant"。 屏幕截图的第二行显示 Error getting token

我在 initOAuthConfig() 中添加了jwks: {'keys': ['https://DOMAIN_PROVIDER/op/v1/keys']},以为它会解决问题,但没有。

// 控制台的应用程序选项卡:会话存储

从控制台的application tab可以看到session-storage中有一些key-value对的数据(localstorage中没有数据)请看下一张截图:

【问题讨论】:

    标签: javascript angular oauth-2.0 angular-oauth2-oidc


    【解决方案1】:

    我的目标是分两个阶段实施您的解决方案:

    • 首先了解 OAuth 和 Open Id Connect 设计模式 - 我希望通过一个简单的 TypeScript 代码示例对此有所帮助
    • 考虑将示例转换为 Angular 的最佳方法,我相信您可以轻松做到这一点

    配置文件

    我喜欢通过 JSON 配置来表达 OAuth 设置 - 请参阅 this file。您可以更新文件以匹配您的配置,运行我的示例,然后希望您会看到返回的令牌。

    API 客户责任

    当 UI 调用 API 时,它必须首先获取访问令牌,并且 UI 还必须处理过期/401 响应 - 请参阅 this class

    OAUTH 客户责任

    API 客户端调用this class 获取令牌,该令牌使用 OIDC 客户端库来管理重定向、响应和返回令牌。

    解释性博文

    另请参阅这些文章,我的目标是保持视觉和易于阅读:

    【讨论】:

      猜你喜欢
      • 2021-05-12
      • 2022-07-07
      • 2020-06-28
      • 2019-11-23
      • 2020-06-06
      • 1970-01-01
      • 2019-09-25
      • 2020-06-15
      • 2022-12-22
      相关资源
      最近更新 更多