简体   繁体   English

Okta+Springboot+angular 的 401 未授权错误

[英]401 unauthorized error for Okta+Springboot+angular

I am working on a springboot+angular app with Okta authentication but I am getting 401 Unauthorized error.我正在开发一个带有 Okta 身份验证的 springboot+angular 应用程序,但我收到 401 Unauthorized 错误。 Following is my code on the front end side:以下是我在前端的代码:

app-routing.module.ts应用程序路由.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { OktaCallbackComponent } from '@okta/okta-angular';
import { OktaAuthGuard } from './app.guard';
import { UserDetailsComponent } from './components/user-details/user-details.component';

const routes: Routes = [
 { path: 'home', canActivate: [OktaAuthGuard], component: UserDetailsComponent },
 { path: 'def', component: OktaCallbackComponent },
 { path: '**', redirectTo: '', pathMatch: 'full' },
];

@NgModule({
 imports: [RouterModule.forRoot(routes)],
 exports: [RouterModule]
})
export class AppRoutingModule { }

app.component.ts app.component.ts

import { Component } from '@angular/core';
import { OktaAuthService } from '@okta/okta-angular';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'users';
isAuthenticated: boolean;
constructor(public oktaAuth: OktaAuthService) {
    // subscribe to authentication state changes
    this.oktaAuth.$authenticationState.subscribe(
    (isAuthenticated: boolean)  => this.isAuthenticated = isAuthenticated
    );
}
async ngOnInit() {
    // get authentication state for immediate use
    this.isAuthenticated = await this.oktaAuth.isAuthenticated();
}
async login() {
    await this.oktaAuth.signInWithRedirect({
    originalUri: '/users'
    });
}
async logout() {
    await this.oktaAuth.signOut();
}
}

app.guard.ts app.guard.ts

import { OktaAuthService } from '@okta/okta-angular';
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable({
providedIn: 'root'
})
export class OktaAuthGuard implements CanActivate {
oktaAuth;
authenticated;
constructor(private okta: OktaAuthService, private router: Router) {
    this.oktaAuth = okta;
}

async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    this.authenticated = await this.okta.isAuthenticated();
    console.log('can activate?', this.authenticated);
    if (this.authenticated) { return true; }
    // Redirect to login flow.
    this.okta.signInWithRedirect();
    return false;
}
}

app.module.ts app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
//import { OktaAuthModule, OktaCallbackComponent } from '@okta/okta-angular';
import {OktaAuthModule, OKTA_CONFIG} from '@okta/okta-angular';
import { UserDetailsComponent } from './components/user-details/user-details.component';
import { ReactiveFormsModule } from '@angular/forms';
import { OktaAuthGuard } from './app.guard';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { XSRFTokenInterceptor } from './xsrf-token-interceptor';
import { AuthInterceptor } from './auth.interceptor';

const oktaConfig = {
issuer: 'https://dev-xxxxxxxx.okta.com/oauth2/default',
redirectUri: window.location.origin + '/users',
clientId: 'xxxxxxxxxxxxxxx',
pkce: true
};

@NgModule({
declarations: [
    AppComponent,
    UserDetailsComponent
],
imports: [
    BrowserModule,
    OktaAuthModule,
    AppRoutingModule,
    HttpClientModule
],
providers: [
    OktaAuthGuard,
    {provide: HTTP_INTERCEPTORS, useClass : XSRFTokenInterceptor, multi: true},
    { provide: OKTA_CONFIG, useValue: oktaConfig },
    {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},],
bootstrap: [AppComponent]
})
export class AppModule { }

auth.interceptor.ts auth.interceptor.ts

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, from } from 'rxjs';
import { OktaAuthService } from '@okta/okta-angular';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

constructor(private oktaAuth: OktaAuthService) {
}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return from(this.handleAccess(request, next));
}

private async handleAccess(request: HttpRequest<any>, next: HttpHandler): Promise<HttpEvent<any>> {

    const accessToken = await this.oktaAuth.getAccessToken();

    if (accessToken) {
    console.log('token: ' + accessToken);
    request = request.clone({
        setHeaders: {
        Authorization: 'Bearer ' + accessToken
        }
    });
    }
    return next.handle(request).toPromise();
}
}

user.service.ts用户服务.ts

 import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
 import { environment } from 'src/environments/environment';
 import { map } from 'rxjs/operators';
 import { HandleError, HttpErrorHandler } from './http-error-handler.service';
 import { catchError } from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})
export class UserService {
private handleError: HandleError;
contactsUrl = environment.contactAPI;
constructor(private http: HttpClient,
    httpErrorHandler: HttpErrorHandler) {
    this.handleError = httpErrorHandler.createHandleError('HeroesService');
}

getUsers() {
 return this.http.get<any>(this.contactsUrl)
    .pipe(map(info => {
        console.log("info: "+info);            
        return info;
    }));

}}

xsrf-token-interceptor.ts xsrf-token-interceptor.ts

 import { Injectable } from '@angular/core';
 import {HttpEvent, HttpRequest, HttpHandler,HttpInterceptor, HttpErrorResponse, 
  HttpXsrfTokenExtractor} from '@angular/common/http';
 import { Observable } from 'rxjs';

@Injectable()
export class XSRFTokenInterceptor implements HttpInterceptor {

constructor(private tokenExtractor: HttpXsrfTokenExtractor) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     return next.handle(req);
   }
}

At the backend:在后端:

SecurityDevConfiguartion.java安全开发配置.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpMethod;
import 
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import java.util.Arrays;


@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)

public class SecurityDevConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
    System.out.println("configure");
    http.cors().and().csrf().disable();
  try {
        http.antMatcher("/**")
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated();
    }catch(Exception e){
        e.printStackTrace();
    }
    http.oauth2ResourceServer();
}

@Bean
CorsConfiguration corsConfiguration() {
    CorsConfiguration corsConfiguration  = new CorsConfiguration();
    corsConfiguration.setAllowCredentials(true);
    corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
    corsConfiguration.setAllowedHeaders(Arrays.asList("Origin", "Access-Control, Allow-Origin", "Content-Type", "Accept", "Authorization", "Origin, Accept", "X-Requested-With", "Access-Control-Request-Method", "Access-Control-Request-Header" )); 
    corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization", "Access-Control-Request-Allow-Origin", "Access-Control-Allow-Credentials"));
    corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
    
    return corsConfiguration ;
}
}

UsersController.java用户控制器.java

import com.example.users.dao.usersDAO;
import com.example.users.model.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class UsersController {

@Autowired
usersDAO usersDAO;

@RequestMapping(value = "/getUsers", method = RequestMethod.GET)
@ResponseBody
public List getUsers(@AuthenticationPrincipal Principal userInfo) throws Exception {
    System.out.println("userInfo: "+userInfo);
    List<Users> users = usersDAO.findAll();
    List<String> l = new ArrayList();
    for(Iterator i=Users.iterator();i.hasNext();){
        Users u = (Users)(i.next());
        l.add(u.getName());
    }
    return l;
}
}

application.properties has client-id and issuer mentioned. application.properties 提到了客户端 ID 和颁发者。 'http//localhost:4200' is mentioned in trusted origins in Okta security.在 Okta 安全性的可信来源中提到了“http//localhost:4200”。

What am I missing/doing wrong?我错过了什么/做错了什么? Any help is appreciated.任何帮助表示赞赏。

Your Okta tenant does have API Access Management feature enabled?您的 Okta 租户是否启用了 API 访问管理功能? Access tokens created through this authorization servers can be verified locally as the signing keys for them are returned under /keys endpoint.通过此授权服务器创建的访问令牌可以在本地验证,因为它们的签名密钥在 /keys 端点下返回。

This feature is free for developer, but paid in production ones.此功能对开发人员免费,但在生产中付费。 If you would like to have this feature enabled on your production tenant.如果您想在生产租户上启用此功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM