Google login in Angular14 with @abacritt/angularx-social-login and the newer Google GIS library

2k Views Asked by At

I want to setup google login in my Angular14 web application with @abacritt/[email protected]. I see that the old Google Sign-In library for Web is deprecated and I want to use the newer one Google Identity Services library. My login is working but I want to do it in redirect mode and not in pop-up mode. How I can do that ?

NB: I use in my login page the button asl-google-signin-button.

You can find attach my used code:

app.module.ts :

import { GoogleLoginProvider, SocialAuthServiceConfig, SocialLoginModule } from '@abacritt/angularx-social-login';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
     {
      provide: 'SocialAuthServiceConfig',
      useValue: {
        autoLogin: false,
        providers: [
          {
            id: GoogleLoginProvider.PROVIDER_ID,
            provider: new GoogleLoginProvider(
              'MY_CLIENT_ID'
            )
          }
        ],
      } as SocialAuthServiceConfig   
    } 
],
   bootstrap: [AppComponent],
})

export class AppModule { }

login.component.html:

        <div class="google-btn">
          <asl-google-signin-button
            type='standard' 
            shape="rectangular" 
            size='medium' 
            theme="filled_blue" 
            text="signin_with" 
            locale="en-GB"
            size="large" 
            logo_alignment="left">
          </asl-google-signin-button>
        </div>

login.component.ts :

ngOnInit(): void {
    this.authService.connectionGoogle().subscribe({
      next: (data: User) => {
        console.log(data)
        this.router.navigateByUrl('home');
      },
      error: (error: any) => {
        console.log(error)
        this.router.navigateByUrl('unauthorized')
      }
    })
}

user.ts :

export interface User{
    id: number;
    first_name: string;
    last_name: string;
    company: Date;
    entity: Date;
    site: number;
    arrival: Date;
    exit: Date;
    profil: string;
    contract: string;
    email: string;
}

auth.service.ts:

...
import { HttpClient } from '@angular/common/http';
import { SocialAuthService, SocialUser } from '@abacritt/angularx-social-login';
import { JwtHelperService } from '@auth0/angular-jwt';

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

  url_user: string = "http://localhost:5000/users/"

  private connectedUser: BehaviorSubject<User> = new BehaviorSubject<User>({} as User)
  private token: BehaviorSubject<string> = new BehaviorSubject<string>('')

  constructor(
    private httpClient: HttpClient,
    private jwtHelper: JwtHelperService,
    private socialAuthService: SocialAuthService
  ) { }

  // getter and setter of user BehaviorSubject

  getUser: Observable<User> = this.connectedUser.asObservable().pipe(
    withLatestFrom(of(JSON.parse(localStorage.getItem('user')!))),
    map(
      ([val, user]) => {
        if (Object.keys(val).length === 0 && user) {
          return user
        }
        return val
      }
    )
  );

  setUser(user: User) {
    localStorage.setItem('user', JSON.stringify(user));
    this.connectedUser.next(user);
  }

  // getter and setter of token access BehaviorSubject

  getToken = this.token.asObservable().pipe(
    withLatestFrom(of(localStorage.getItem('access_token')!)),
    map(([val, local]) => {
      if (!val && local) {
        return !this.jwtHelper.isTokenExpired(local)
      }
      return !this.jwtHelper.isTokenExpired(val)
      }
    )
  )

  setToken(token: string): void {
    localStorage.setItem('access_token', token);
    this.token.next(token);
  }

   // main google login method

  connectionGoogle(): Observable<User> {
    return this.socialAuthService.authState.pipe(
      concatMap((res: SocialUser) => {
        return this.googleLoginAndGetUser(res.idToken)
      }),
      tap(res => this.setUser(res))
    )
  }

  googleLoginAndGetUser(data: string): Observable<User> {
    return this.googleLogin(data).pipe(
      concatMap((res: any) => {
        this.setToken(res.access_token);
        const parseJwt = JSON.parse(atob(res.access_token.split('.')[1]));
        const idUser = parseJwt.sub;
        return this.getUser(idUser)
        )
      })
    )
  }

  //endpoint to google login in my backend server (return access token)

  googleLogin(idToken: string) {
    const obj = {'idToken': idToken};
    return this.httpClient.post<any>(this.url_user + 'glogin', obj)
  }

  //endpoint to get User informations in my backend server (should have a valid access Token before). I add the header request in the interceptor. 

  getUser(idUser: number): Observable<User> {
    return this.httpClient.get<User>(this.url_user + idUser)
  }

}

home.component.ts:

export class HomeComponent {

  constructor(
    private authService: AuthService
  ) { }
  
  user$: Observable<User> = this.authService.getUser;
  isLogin$: Observable<boolean> = this.authService.getToken;
}

home.component.html:

<mat-drawer-container class="example-container">
        <h1 *ngIf="isLogin$ | async"> Welcome To App</h1>
        <div *ngIf="(user$ | async) as user">
            <h3>Hi {{ user.first_name | uppercase }}</h3>
        </div>
</mat-drawer-container>

and the screen of the client ID of my application :

enter image description here

what you can suggest me to do redirect mode ?

Don't hesitate if you know other libraries that allow to do that.

Thanks in advance.

0

There are 0 best solutions below