簡體   English   中英

Okta 組件在運行時給出錯誤無法讀取未定義的屬性(讀取“_oktaUserAgent”)

[英]Okta Component giving error at runtime Cannot read properties of undefined (reading '_oktaUserAgent')

我在我的項目中使用 OKTA 授權,但在運行時遇到錯誤

嘗試用谷歌搜索,但找不到任何相關的解決方案

這是錯誤

TypeError: Cannot read properties of undefined (reading '_oktaUserAgent')
    at new OktaAuthModule (okta-angular.js:236)
    at Object.OktaAuthModule_Factory [as factory] (okta-angular.js:260)
    at R3Injector.hydrate (core.js:11354)
    at R3Injector.get (core.js:11175)
    at core.js:11212
    at Set.forEach (<anonymous>)
    at R3Injector._resolveInjectorDefTypes (core.js:11212)
    at new NgModuleRef$1 (core.js:24308)
    at NgModuleFactory$1.create (core.js:24362)
    at core.js:28101

這是我的 Appmodule.ts

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

import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { ProductListComponent } from './components/product-list/product-list.component';
import { ProductService } from './service/product.service';
import { Router, RouterModule, Routes } from '@angular/router';
import { ProductCategoryMenuComponent } from './components/product-category-menu/product-category-menu.component';
import { SearchComponent } from './components/search/search.component';
import { ProductDetailsComponent } from './components/product-details/product-details.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { CartStatusComponent } from './components/cart-status/cart-status.component';
import { CartDetailsComponent } from './components/cart-details/cart-details.component';
import { CheckoutComponent } from './components/checkout/checkout.component';
import { ReactiveFormsModule } from '@angular/forms';
import { LoginComponent } from './components/login/login.component';
import {
  OKTA_CONFIG,
  OktaAuthModule,
  OktaCallbackComponent
} from '@okta/okta-angular';
import myAppConfig from './config/my-app-config';
import { LoginStatusComponent } from './components/login-status/login-status.component';

const oktaConfig = Object.assign({
  onAuthRequired: (injector) =>{
    const router = injector.get(Router);
    router.navigate(['/login']);
  }
}, myAppConfig.oidc);


const routes: Routes = [
  {path: 'login/callback', component: OktaCallbackComponent},
  {path: 'login', component: LoginComponent},
  {path: 'checkout', component: CheckoutComponent },
  {path: 'cart-details', component: CartDetailsComponent },
  {path: 'products/:id', component: ProductDetailsComponent },
  {path: 'search/:keyword', component: ProductListComponent },
  {path: 'category/:id', component: ProductListComponent},
  {path: 'category', component: ProductListComponent},
  {path: 'products', component: ProductListComponent},
  {path: '', redirectTo: '/products', pathMatch: 'full'},
  {path: '**', redirectTo: '/products', pathMatch: 'full'}
];

@NgModule({
  declarations: [
    AppComponent,
    ProductListComponent,
    ProductCategoryMenuComponent,
    SearchComponent,
    ProductDetailsComponent,
    CartStatusComponent,
    CartDetailsComponent,
    CheckoutComponent,
    LoginComponent,
    LoginStatusComponent
  ],
  imports: [
    RouterModule.forRoot(routes),
    BrowserModule,
    HttpClientModule,
    NgbModule,
    ReactiveFormsModule,
    OktaAuthModule
  ],
  providers: [ProductService, {provide: OKTA_CONFIG, useValue: oktaConfig}],
  bootstrap: [AppComponent]
})
export class AppModule { }

這是我對okta myAppConfig的配置

export default {

    oidc: {
        clientId: '<your client id>',
        issuer: 'https:<your url>/oauth2/default',
        redirectUri: 'http://localhost:4200/login/callback',
        scopes: ['openid', 'profile', 'email']
    }

}

這是我的登錄狀態組件在應用程序開始時加載

import { Component, OnInit } from '@angular/core';
import { OktaAuthStateService } from '@okta/okta-angular';
import { OktaAuth } from '@okta/okta-auth-js';

@Component({
  selector: 'app-login-status',
  templateUrl: './login-status.component.html',
  styleUrls: ['./login-status.component.css']
})
export class LoginStatusComponent implements OnInit {

  isAuthenticated: boolean = false;
  userFullName: string;

  constructor(private oktaAuth: OktaAuth,private authstateService: OktaAuthStateService) { }

  ngOnInit(): void {
    this.oktaAuth.authStateManager.subscribe(
      (result)=>{
        this.isAuthenticated = result
        this.getUserDetails()
      }
    )
  }


  getUserDetails() {
    if(this.isAuthenticated){

      this.oktaAuth.getUser().then(
        (res)=>{
          this.userFullName = res.name
        }
      )
    }
  }

  logout(){
    this.oktaAuth.signOut();
  }

}

這是我的登錄組件

import { Component, OnInit } from '@angular/core';
import {  OktaAuthStateService } from '@okta/okta-angular';
//import { OktaAuthService } from '@okta/okta-angular';
import * as OktaSignIn from '@okta/okta-signin-widget';
import myAppConfig from 'src/app/config/my-app-config';
import { OktaAuth } from '@okta/okta-auth-js';



@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  

  oktaSignin: any;


  constructor(private oktaAuthService: OktaAuthStateService,private oktaAuth: OktaAuth) {

    this.oktaSignin = new this.oktaSignin({
      baseUrl: myAppConfig.oidc.issuer.split('/oauth2')[0],
      clientId: myAppConfig.oidc.clientId,
      redirectUri: myAppConfig.oidc.redirectUri,
      authParams: {
        pkce: true,
        issuer: myAppConfig.oidc.issuer,
        scopes: myAppConfig.oidc.scopes
      }
    })
   }

  ngOnInit(): void {
    this.oktaSignin.remove();

    this.oktaSignin.renderEl(
      {
        el: '#okta-sign-in-widget'  // this name should be same as div tag id in login.component.html
      },
      (response) =>{
        if (response.status === 'SUCCESS') {
          this.oktaAuth.signInWithRedirect();
        }
      },
      (error) => {
        throw error;
      }
    )
  }

}

問題是您的源代碼 Okta Angular 與新版本 Okta Angular 不兼容...按照說明遷移: https ://github.com/okta/okta-angular/blob/master/MIGRATING.md

我已經解決了這個問題,因為這個源代碼來自與我在 udemy 上的同一門課程:D。

我正在使用 Okta 5

更改app.module.ts

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

import { AppComponent } from './app.component';
import { ProductListComponent } from './components/product-list/product-list.component';
import { HttpClientModule } from '@angular/common/http';
import { ProductService } from './services/product.service';
import { RouterModule, Routes } from '@angular/router';
import { ProductCategoryMenuComponent } from './components/product-category-menu/product-category-menu.component';
import { SearchComponent } from './components/search/search.component';
import { ProductDetailsComponent } from './components/product-details/product-details.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { CartStatusComponent } from './components/cart-status/cart-status.component';
import { CartDetailsComponent } from './components/cart-details/cart-details.component';
import { CheckoutComponent } from './components/checkout/checkout.component';
import { ReactiveFormsModule } from '@angular/forms';
import { LoginComponent } from './components/login/login.component';
import { LoginStatusComponent } from './components/login-status/login-status.component';

import {
  OKTA_CONFIG,
  OktaAuthModule,
  OktaCallbackComponent
} from '@okta/okta-angular';

import { OktaAuth } from '@okta/okta-auth-js';
import appConfig from './config/app-config';

// create routes
const routes: Routes = [ 
  { path: 'login/callback', component: OktaCallbackComponent },
  { path: 'login', component: LoginComponent },
  { path: 'checkout', component: CheckoutComponent },
  { path: 'cart-details', component: CartDetailsComponent },
  { path: 'products/:id', component: ProductDetailsComponent },
  { path: 'search/:keyword', component: ProductListComponent },
  { path: 'category/:id/:name', component: ProductListComponent },
  { path: 'category', component: ProductListComponent },
  { path: 'products', component: ProductListComponent },   
  { path: '', redirectTo: '/products', pathMatch: 'full' },
  { path: '**', redirectTo: '/products', pathMatch: 'full' }
];

const oktaAuth = new OktaAuth(appConfig.oidc); // the name variable must oktaAuth

@NgModule({
  declarations: [
    AppComponent,
    ProductListComponent,
    ProductCategoryMenuComponent,
    SearchComponent,
    ProductDetailsComponent,
    CartStatusComponent,
    CartDetailsComponent,
    CheckoutComponent,
    LoginComponent,
    LoginStatusComponent
  ],
  imports: [
    RouterModule.forRoot(routes),
    BrowserModule,
    HttpClientModule,
    NgbModule,
    ReactiveFormsModule,
    OktaAuthModule
  ],
  providers: [ProductService, {provide: OKTA_CONFIG, useValue: {oktaAuth}}],
  bootstrap: [AppComponent]
})
export class AppModule { }

文件login.component.ts

import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import OktaSignIn from '@okta/okta-signin-widget';
import { OKTA_AUTH } from '@okta/okta-angular';

import appConfig from '../../config/app-config';
import { OktaAuth } from '@okta/okta-auth-js';

/**
 * for more information: https://github.com/okta/okta-angular
 * for change/migration version future read: https://github.com/okta/okta-angular/blob/master/MIGRATING.md
 */

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit, OnDestroy {

  oktaSignin: any;

  constructor(@Inject(OKTA_AUTH) private oktaAuth: OktaAuth) {

    this.oktaSignin = new OktaSignIn({
      logo: 'assets/images/angular-logo.svg',
      baseUrl: appConfig.oidc.issuer.split('/oauth2')[0],
      clientId: appConfig.oidc.clientId,
      redirectUri: appConfig.oidc.redirectUri,
      authParams: {
        pkce: true,
        issuer: appConfig.oidc.issuer,
        scopes: appConfig.oidc.scopes
      }
    });
  }

  ngOnInit(): void {
    this.oktaSignin.remove(); // remove all to clean

    this.oktaSignin.renderEl({
      el: '#okta-sign-in-widget' // this name should same as div tag id in component.html
    },
    (response) => {
      if (response.status === 'SUCCESS') {
        this.oktaAuth.signInWithRedirect();
      }
    },
    (error) => {
      throw error;
    }
    );
  }

  ngOnDestroy(): void {
    this.oktaSignin.remove();
  }

}

文件login-status.component

import { Component, Inject, OnInit } from '@angular/core';
import { OKTA_AUTH } from '@okta/okta-angular';
import { OktaAuth } from '@okta/okta-auth-js';

@Component({
  selector: 'app-login-status',
  templateUrl: './login-status.component.html',
  styleUrls: ['./login-status.component.css']
})
export class LoginStatusComponent implements OnInit {

  isAuthenticated: boolean = false;
  userFullName: string = "";

  constructor(@Inject(OKTA_AUTH) private oktaAuth: OktaAuth) {
    this.oktaAuth.authStateManager.subscribe(
      isAuth => this.isAuthenticated = isAuth
    );
  }

  async ngOnInit() {
    this.isAuthenticated = await this.oktaAuth.isAuthenticated();
    
    if (this.isAuthenticated) {
      const userClaim = await this.oktaAuth.getUser();
      this.userFullName = userClaim.name || "";
    }
    console.log("Autentication = " + this.isAuthenticated);
    console.log("Username = " + this.userFullName);
  }

  async logout() {
    // terminates the session
    await this.oktaAuth.signOut();
  }

}

我也更新文件:

文件tsconfig.json

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noImplicitAny": false,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2017",
    "module": "es2020",
    "lib": [
      "es2020",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true,
    "esModuleInterop": true, // <- add this
    "allowSyntheticDefaultImports": true // <-- add this

  }
}

我更新到angular.json部分:

...
"build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "allowedCommonJsDependencies": [
              "lodash",
              "@babel/runtime-corejs3"
           ],
...

您使用的是什么版本的 Okta Angular? 如果是 v4,則發生了重大變化。 請參閱遷移指南或此示例升級

您在 app.module.ts 的 provider 行中缺少一組圍繞 oktaAuth 的花括號

{ provide: OKTA_CONFIG, useValue: { oktaAuth } },

來自[https://gitmemory.cn/repo/okta/okta-angular/issues/71][1]

在“LoginStatusComponent”和“LoginComponent”的“構造函數”中的“private oktaAuth: OktaAuth”之前使用@Inject(OKTA_AUTH)

我有同樣的問題。 嘗試降級節點版本並重新安裝okta/angular包:

npm i @okta/okta-angular

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM