Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth2.0 NullInjectorError: R3InjectorError(Environment Injector)[_GoogleOAuthService -> _OAuthService -> _OAuthService]: NullInjectorError: No provider for _OAuthService! #706

Open
ggraur opened this issue Dec 6, 2024 · 0 comments

Comments

@ggraur
Copy link

ggraur commented Dec 6, 2024

Hi guys very nubby with oAuth2.0, trying to implement with 'Google API' using Angular 19.0.2. below are my code

/main.ts/
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { routes } from './app/app.routes';
import { provideRouter } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
import { GoogleApiService } from './app/services/google-api.service';
import { MyCustomInterceptor } from './app/interceptors/my-custom.interceptor';
import { HTTP_INTERCEPTORS } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
OAuthService, // Provide OAuthService globally
GoogleApiService, // Provide GoogleOAuthService globally
{
provide: HTTP_INTERCEPTORS, // Register the custom HTTP interceptor
useClass: MyCustomInterceptor,
multi: true, // Allow multiple interceptors
},
]
};

bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));

/main.server.ts/
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { config } from './app/app.config.server';

const bootstrap = () => bootstrapApplication(AppComponent, config);

export default bootstrap;

/index.html/
<!doctype html>

<title>MyTest01</title>

/app.module.ts/

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { BrowserModule } from '@angular/platform-browser';
import { OAuthModule } from 'angular-oauth2-oidc';
import { AppComponent } from './app.component';

@NgModule({
imports: [
CommonModule,
BrowserModule,
AppComponent,
OAuthModule.forRoot()
],
declarations: [ ]
})
export class AppModule { }

/app.config.ts/

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
import {provideHttpClient } from '@angular/common/http'

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
provideZoneChangeDetection({ eventCoalescing: true }),
provideClientHydration(withEventReplay())]
};

/app.config.server.ts/
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { provideServerRoutesConfig } from '@angular/ssr';
import { appConfig } from './app.config';
import { serverRoutes } from './app.routes.server';

const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering(),
provideServerRoutesConfig(serverRoutes)
]
};

export const config = mergeApplicationConfig(appConfig, serverConfig);

/app.component.ts/
import { Component } from '@angular/core';

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { GoogleApiService } from './services/google-api.service';
import { UserInfo } from './interfaces/UserInfo';
import { HttpClient } from '@angular/common/http';
import { MyCustomInterceptor } from './interceptors/my-custom.interceptor';
import { OAuthService } from 'angular-oauth2-oidc';

@component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
standalone: true, // This marks the component as standalone
imports: [RouterModule, CommonModule], // Import RouterModule to handle router-outlet
providers: [GoogleApiService, HttpClient, MyCustomInterceptor], // Add both services here
})
export class AppComponent {
title(title: any) {
throw new Error('Method not implemented.');
}
userinfo?:UserInfo;

constructor(public readonly googleApi: GoogleApiService,private oauthService: OAuthService) {
googleApi.userProfileSubject.subscribe(info=>{
this.userinfo = info;
})
}

isLoggedIn():boolean{
return this.googleApi.isLoggedIn();
}

logout(){
this.googleApi.signOut();
}
}
/app.component.html/

hi and Welcome!
Name: {{userinfo?.info?.name}}
Name: {{userinfo?.info?.email}}
Name: {{userinfo?.info?.picture}}
Log Out From Google

/*google api service */

import { Injectable } from '@angular/core';
import { AuthConfig,OAuthService } from 'angular-oauth2-oidc';
import { Subject } from 'rxjs';
import { UserInfo } from '../interfaces/UserInfo';

const oAuthConfig : AuthConfig={
issuer:'https://accounts.google.com',
strictDiscoveryDocumentValidation:false,
redirectUri: 'http://localhost:4200', // Check if window is defined
clientId:'xxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
scope: "openid profile email",

}

@Injectable({
providedIn: 'root'
})
export class GoogleApiService {

userProfileSubject = new Subject()

constructor(private readonly oAuthService:OAuthService) {

oAuthService.configure(oAuthConfig);
oAuthService.loadDiscoveryDocument().then(()=>{
  oAuthService.tryLoginImplicitFlow().then(()=>{
    if(!oAuthService.hasValidAccessToken()){
      oAuthService.initLoginFlow()
    }else{
      oAuthService.loadUserProfile().then((userProfile)=>{
        console.log(JSON.stringify(userProfile))
        this.userProfileSubject.next(userProfile as UserInfo)
      })
    }
  })
})

}
isLoggedIn():boolean{
return this.oAuthService.hasValidAccessToken()
}
signOut(){
this.oAuthService.logOut()
}

}

/user model/
export interface UserInfo {
info:{
sub:string,
email:string,
name:string,
picture:string
}
}

/interceptor/
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpInterceptor,
HttpErrorResponse,
HttpHeaders,
HttpResponse
} from '@angular/common/http';
import { Observable, Subject, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { GoogleApiService } from '../services/google-api.service';
import { UserInfo } from '../interfaces/UserInfo';

@Injectable()
export class MyCustomInterceptor implements HttpInterceptor {
userProfileSubject: Subject | undefined;
constructor(private googleOAuthService: GoogleApiService) {}

intercept(request: HttpRequest, next: HttpHandler): Observable {
// Clone the request and add the Authorization header if the user is logged in
let authReq = request;

if (this.googleOAuthService.isLoggedIn()) {
 
this.userProfileSubject = this.googleOAuthService.userProfileSubject;
  const token = this.googleOAuthService. userProfile?.access_token;
  if (token) {
    authReq = request.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,  // Add the token to the request headers
      },
    });
  }
}

// Send the cloned request with the Authorization header to the next handler
return next.handle(authReq).pipe(
  map((event) => {
    if (event instanceof HttpResponse) {
      // You can modify the response if necessary, or log it
    }
    return event;
  }),
  catchError((error: HttpErrorResponse) => {
    // Handle 401 Unauthorized error (or any other error)
    if (error.status === 401) {
      console.error('Unauthorized access - perhaps the user is not logged in?');
      // Optionally, you can add logic to log the user out or redirect to a login page
      // this.authService.logout(); // Example: log out the user
    }
    return throwError(() => error); // Re-throw the error
  })
);

}
}

the error i'm getting
" ERROR Error [NullInjectorError]: R3InjectorError(Standalone[_AppComponent])[_OAuthService -> _OAuthService -> _OAuthService]:
NullInjectorError: No provider for _OAuthService!
at NullInjector.get (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:1659:21)
at R3Injector.get (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:2006:27)
at R3Injector.get (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:2006:27)
at R3Injector.get (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:2006:27)
at ChainedInjector.get (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:3568:32)
at lookupTokenUsingModuleInjector (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:3746:31)
at getOrCreateInjectable (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:3771:10) at ɵɵdirectiveInject (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:8240:17)
at Module.ɵɵinject (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace.angular\cache\19.0.3\my-test01\vite\deps_ssr\chunk-F6BYPTTE.js:1398:59)
at NodeInjectorFactory.GoogleApiService_Factory (C:\Gitea\LocalRepo\OAuth2Project\FrontEnd\MyAppWorkspace\projects\my-test01\src\app\services\google-api.service.ts:19:30) {
ngTempTokenPath: null,
ngTokenPath: [ '_OAuthService', '_OAuthService', '_OAuthService' ]
}"
that is my code, ill be appreciated if any may help
thanks in advance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant