auth0 receive error (Login required )when I attempt to access my auth0 protected api

Viewed 767

I am using angular on the front end, django rest framework on the backend

I am using auth0 to handle authentication.

I had everything working fine and then I followed the docs on how to secure an api with a users auth0 credentials.

How I have this schema. A user logs in with auth0 then my system sees if a user is connected with that auth0id if not it prompts the user to create a user for my system.

So a auth0 user is attached to a system user

Regardless

when I login to my system using auth0 I console log the user object that is returned and that console log does contain the user object.

The user object token is stored in localstorage.

The auth0 auth.service is below. It is pretty standard from what came from the auth0 docs:

import { Injectable } from '@angular/core';
import createAuth0Client from '@auth0/auth0-spa-js';
import Auth0Client from '@auth0/auth0-spa-js/dist/typings/Auth0Client';
import { from, of, Observable, BehaviorSubject, combineLatest, throwError } from 'rxjs';
import { tap, catchError, concatMap, shareReplay } from 'rxjs/operators';
import { Router } from '@angular/router';
import {environment} from '../../environments/environment';
import {HttpClient} from '@angular/common/http';

@Injectable()
export class AuthService {
  // Create an observable of Auth0 instance of client
  auth0Client$ = (from(
    createAuth0Client({
      domain: environment.auth0_domain,
      client_id: environment.auth0_client_id,
      redirect_uri: `${window.location.origin}`,
      useRefreshTokens: true,
      cacheLocation: 'localstorage'
    })
  ) as Observable<Auth0Client>).pipe(
    shareReplay(1), // Every subscription receives the same shared value
    catchError(err => throwError(err))
  );
  // Define observables for SDK methods that return promises by default
  // For each Auth0 SDK method, first ensure the client instance is ready
  // concatMap: Using the client instance, call SDK method; SDK returns a promise
  // from: Convert that resulting promise into an observable
  isAuthenticated$ = this.auth0Client$.pipe(
    concatMap((client: Auth0Client) => from(client.isAuthenticated())),
    tap(res => this.loggedIn = res)
  );
  handleRedirectCallback$ = this.auth0Client$.pipe(
    concatMap((client: Auth0Client) => from(client.handleRedirectCallback()))
  );
  // Create subject and public observable of user profile data
  private userProfileSubject$ = new BehaviorSubject<any>(null);
  userProfile$ = this.userProfileSubject$.asObservable();
  // Create a local property for login status
  loggedIn: boolean = null;

  constructor(private router: Router, private http: HttpClient) {
    // On initial load, check authentication state with authorization server
    // Set up local auth streams if user is already authenticated
    this.localAuthSetup();
    // Handle redirect from Auth0 login
    this.handleAuthCallback();
  }

  // When calling, options can be passed if desired
  // https://auth0.github.io/auth0-spa-js/classes/auth0client.html#getuser
  getUser$(options?): Observable<any> {
    return this.auth0Client$.pipe(
      concatMap((client: Auth0Client) => from(client.getUser(options))),
      tap(user => {
        this.userProfileSubject$.next(user);
        console.log(user);
      })
    );
  }
  // for when a user attempts to sign up by clicking the log in button vs clicking the sign up button
  // these set of functions and class variables deal with that

  rawsenduserobject(): Observable<any>{
    return this.userProfile$;
  }




  // end functions and variables that deal with improper user sign up

  private localAuthSetup() {
    // This should only be called on app initialization
    // Set up local authentication streams
    const checkAuth$ = this.isAuthenticated$.pipe(
      concatMap((loggedIn: boolean) => {
        if (loggedIn) {
          // If authenticated, get user and set in app
          // NOTE: you could pass options here if needed
          return this.getUser$();
        }
        // If not authenticated, return stream that emits 'false'
        return of(loggedIn);
      })
    );
    checkAuth$.subscribe();
  }

  login(redirectPath: string = '/') {
    // A desired redirect path can be passed to login method
    // (e.g., from a route guard)
    // Ensure Auth0 client instance exists
    this.auth0Client$.subscribe((client: Auth0Client) => {
      // Call method to log in
      client.loginWithRedirect({
        redirect_uri: `${window.location.origin}`,
        appState: { target: redirectPath }
      });
    });
  }

  private handleAuthCallback() {
    // Call when app reloads after user logs in with Auth0
    const params = window.location.search;
    if (params.includes('code=') && params.includes('state=')) {
      let targetRoute: string; // Path to redirect to after login processsed
      const authComplete$ = this.handleRedirectCallback$.pipe(
        // Have client, now call method to handle auth callback redirect
        tap(cbRes => {
          // Get and set target redirect route from callback results
          targetRoute = cbRes.appState && cbRes.appState.target ? cbRes.appState.target : '/';
        }),
        concatMap(() => {
          // Redirect callback complete; get user and login status
          return combineLatest([
            this.getUser$(),
            this.isAuthenticated$
          ]);
        })
      );
      // Subscribe to authentication completion observable
      // Response will be an array of user and login status
      authComplete$.subscribe(([user, loggedIn]) => {
        // Redirect to target route after callback processing
        this.router.navigate([targetRoute]);
      });
    }
  }

  logout() {
    // Ensure Auth0 client instance exists
    this.auth0Client$.subscribe((client: Auth0Client) => {
      // Call method to log out
      client.logout({
        client_id: environment.auth0_client_id,
        returnTo: `${window.location.origin}`
      });
    });
  }

  // for sending the user object from the backend
  serversidebehaviorsubject = new BehaviorSubject(null);

  sendserversideuser(user){
    this.serversidebehaviorsubject.next(user);
  }

  receiveserversideuser():Observable<any>{
    return this.serversidebehaviorsubject.asObservable();
  }

}

the http interceptor again mostly from what was presented in the docs is below:

imports: [
    BrowserModule,
    RouterModule,
    FontAwesomeModule,
    RecaptchaV3Module,
    FormsModule,
    HttpClientModule,
    AppRoutingModule,
    HttpClientModule,
    AuthModule.forRoot({
      domain: environment.auth0_domain,
      clientId: environment.auth0_client_id,
      redirectUri: window.location.origin,

      // The AuthHttpInterceptor configuration
      httpInterceptor: {
        allowedList: [
          {
            uri: 'http://127.0.0.1:8000/api/*'
          }

        ],
      },
    })

  ],
  providers: [Addemailtomarketinglistservice,
    { provide: HTTP_INTERCEPTORS, useClass: AuthHttpInterceptor, multi: true },
    {provide: RECAPTCHA_V3_SITE_KEY, useValue: environment.recaptcha_site_key },
  Googlerecaptchaservice, AuthService, HidecomponentService, S3Service, AuthClientConfig],
  bootstrap: [AppComponent]

yet now whenever I call my backend api I get this error:

ERROR Error: Login required
    at new n (auth0-spa-js.production.esm.js:15)
    at Function.n.fromPayload (auth0-spa-js.production.esm.js:15)
    at s (auth0-spa-js.production.esm.js:15)
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:27492)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)
    at invokeTask (zone-evergreen.js:1621)
    at globalZoneAwareCallback (zone-evergreen.js:1658)
0 Answers
Related