你好,将你的前端更改为:
<Button
color="secondary"
startIcon={<GoogleIcon />}
onClick={googleLogin}
fullWidth
variant="outlined"
size="large"
>
Login with Google
</Button>
并添加 googleLogin 函数如下:
const googleLogin = async () => {
try {
window.open(`http://localhost:3001/auth/google-logins/${from.replaceAll('/', '@')}`, "_self");
} catch (ex) {
console.log(ex)
}
}
像这样更改您的路线文件:
<Route path="google-oauth-success-redirect">
<Route path=":accessToken/:refreshToken/:from" element={<GoogleOAuthSuccessRedirect />} />
</Route>
并添加 GoogleOAuthSuccessRedirect 组件:
import React, { useEffect } from 'react'
import { useNavigate, useParams } from 'react-router-dom';
import { setAuthTokens } from 'redux/features/auth/authSlice';
import { useAppDispatch } from 'redux/hooks';
type Props = {}
const GoogleOAuthSuccessRedirect = (props: Props) => {
let { accessToken, refreshToken, from } = useParams();
const navigate = useNavigate();
const dispatch = useAppDispatch()
useEffect(() => {
if (from && accessToken && refreshToken) {
dispatch(setAuthTokens({ accessToken, refreshToken }))
navigate('/' + from, { replace: true });
}
}, [accessToken, dispatch, from, navigate, refreshToken])
return (
<div>Loading...</div>
)
}
export default GoogleOAuthSuccessRedirect
转到应用程序的后端并进行如下更改:
在控制器上:
@Get('google-logins/:from')
@UseGuards(GoogleOauthGuard)
async googleLogin(@Req() req: Request) {
}
@Get('google/callback')
@UseGuards(GoogleOauthGuard)
async googleLoginCallback(
@Req() req: Request,
@Res() res: Response,
) {
const auth = await this.authService.login(req.user);
res.redirect(`http://localhost:3000/google-oauth-success-redirect/${auth.accessToken}/${auth.refreshToken}${req.params.from}`)
}
关于谷歌策略:
authenticate(req: any, options: any) {
if (!options?.state) {
options = { ...options, state: req.params.from }
}
return super.authenticate(req, options)
}
和谷歌oauth守卫如下:
import {
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AuthGuard, IAuthModuleOptions } from '@nestjs/passport';
import { Request, Response } from 'express';
@Injectable()
export class GoogleOauthGuard extends AuthGuard('google') {
constructor(private configService: ConfigService) {
super({
// accessType: 'offline',
// response_type: "code",
// display: 'popup',
// approvalPrompt: 'auto',
prompt: 'select_account', //"consent"
});
}
async canActivate(context: ExecutionContext) {
try {
const request = context.switchToHttp().getRequest() as Request;
const from = (request.query.state as string)?.replace(/\@/g, '/')
// response.setHeader('X-Frame-Options', 'SAMEORIGIN');
// await super.logIn(request) //to enabling session / we dont need it
const activate = (await super.canActivate(context)) as boolean;
request.params.from = from
return activate;
} catch (ex) {
throw ex
}
}
}
最后,您可以访问我的应用程序的完整源代码,该应用程序是使用 React TypeScript(redux 工具包 rtk 查询)和 Nestjs 实现的,其中包含 google oauth2 流和 Passport.js。resource https://github.com/mehdiparastar/MUITNT_boilerplate/commit/114d6d77af65dac3288760506403f527fe08418e