如何在 Angular 中实现使用 google 登录

RAH*_*NDU 8 google-api openid-connect google-signin angular angular-social-login

我正在尝试在我的角度应用程序中实现谷歌登录功能。我在这里使用了两个包@abacritt/angularx-social-loginangular-oauth2-oidc

我创建了一个名为google-authentication.service.ts与此存储库Link相同的自定义提供程序。使用这种方法,成功登录后,对话框不会关闭,而且我也无法获取登录用户的详细信息。

问题:请建议一种在成功登录后关闭对话框并获取登录用户凭据的方法

谷歌身份验证.service.ts:

@Injectable()
export class GoogleAuthenticationService implements LoginProvider {
    constructor(private readonly _oAuthService: OAuthService) {
        this.createConfiguration();
    }

    private readonly _tokenReceived$ = this._oAuthService.events.pipe(
        filter((e) => e.type === 'token_received'),
        map(() => true as const)
    );

    private createConfiguration(): void {
        let redirectUri = window.location.origin + window.location.pathname;
        if (redirectUri.endsWith('/')) {
            redirectUri = redirectUri.substring(0, redirectUri.length - 1);
        }

        this._oAuthService.configure({
            issuer: 'https://accounts.google.com',
            strictDiscoveryDocumentValidation: false,
            redirectUri,
            silentRefreshRedirectUri: redirectUri,
            useSilentRefresh: true,
            clientId: environment.googleClientId,
            scope: 'openid profile email'
        });
    }

    async initialize(autoLogin?: boolean): Promise<void> {
        await this._oAuthService.loadDiscoveryDocument();
        if (autoLogin) {
            await this._oAuthService.tryLoginImplicitFlow();
        }
    }

    async signIn(): Promise<SocialUser> {
        const tokenReceivedPromise = firstValueFrom(this._tokenReceived$);

        await this._oAuthService.initImplicitFlowInPopup();
        await tokenReceivedPromise;

        return this.createUser(this._oAuthService.getIdToken());
    }

    async getLoginStatus(): Promise<SocialUser> {
        if (this._oAuthService.hasValidIdToken()) {
            return this.createUser(this._oAuthService.getIdToken());
        } else {
            throw `No user is currently logged in`;
        }
    }

    async signOut(revoke?: boolean): Promise<void> {
        if (revoke) {
            this._oAuthService.revokeTokenAndLogout(true, true);
        } else {
            this._oAuthService.logOut(true);
        }
    }

    private createUser(idToken: string): SocialUser {
        const user = new SocialUser();
        const payload = JSON.parse(window.atob(idToken.split('.')[1]));
        user.idToken = idToken;
        user.id = payload.sub;
        user.name = payload.name;
        user.email = payload.email;
        user.photoUrl = payload.picture;
        user.firstName = payload['given_name'];
        user.lastName = payload['family_name'];
        return user;
    }
}
Run Code Online (Sandbox Code Playgroud)

登录组件.ts

ngOnInit(): void {
    this._googleAuthService.initialize();
}

signUpWithGoogle(event: Event): void {
    this._googleAuthService
        .signIn()
        .then((user) => {
            //not showing anything in console
            console.log(user);
        })
        .catch((error) => {
            console.log(error);
        });
}
Run Code Online (Sandbox Code Playgroud)

小智 16

这对我来说是这样的工作。根据 Google 的新文档(https://developers.google.com/identity/gsi/web/guides/overview),您应该按照以下步骤操作:

  1. 在谷歌云控制台平台创建谷歌应用程序并生成客户端ID。

  2. 加载客户端库。在Angular 项目的 index.html 文件的标签之间添加此脚本“ <script src="https://accounts.google.com/gsi/clientasync defer>” 。<head></head>

  3. 将此代码添加到您希望具有“使用 Google 按钮登录”的组件中的 ngOnInit() 函数上。

ngOnInit() {
  // @ts-ignore
  google.accounts.id.initialize({
    client_id: "YOUR GOOGLE CLIENT ID",
    callback: this.handleCredentialResponse.bind(this),
    auto_select: false,
    cancel_on_tap_outside: true,

  });
  // @ts-ignore
  google.accounts.id.renderButton(
  // @ts-ignore
  document.getElementById("google-button"),
    { theme: "outline", size: "large", width: "100%" }
  );
  // @ts-ignore
  google.accounts.id.prompt((notification: PromptMomentNotification) => {});
}  
Run Code Online (Sandbox Code Playgroud)
async handleCredentialResponse(response: any) {
  // Here will be your response from Google.
  console.log(response);
}
Run Code Online (Sandbox Code Playgroud)
  1. 将 div 或 button 元素添加到该组件的 html 文件中,并使用您在初始化中提到的相同 id。(“谷歌按钮”):

<div class="" id="google-button"></div>.

如果您有任何问题,请告诉我。

  • 对于使用此解决方案的任何人来说,似乎是从_外部 Angular_ 调用“handleCredentialResponse”。如果你想在 Angular 内部做一些事情,例如改变一个组件变量,你需要使用 NgZone。只需在构造函数中导入 NgZone,然后在“handleCredentialResponse”中调用从“this.ngZone.run()”运行 _inside Angular_ 所需的任何内容。例如,要更改组件中的 localVariable,`this.ngZone.run(() =&gt; this.localVariable = "newValue")` (4认同)