pocketbase + google-oauth + react-router + react-query로 반응 인증
32526 단어 oauthreactpocketbasegooglecloud
소개
이 기사에서는 firebase에서 만든 앱을 pocketbase로 포팅하려고 합니다.
1 : 인증
2022년에는 사용자와 개발자가 쉽게 사용할 수 있도록 공급자 로그인이 기본 인증 옵션이 되어야 합니다.
사용자는 한 번의 클릭으로 로그인할 수 있으며 개발자는 사용자 암호 확인, 저장 및 관리에 대해 걱정할 필요가 없습니다.
Firebase는 이를 구현하는 간단한 방법을 제공하지만(특히 Google에서는 firebase가 기본적으로 구성된 클라이언트 토큰인 클라이언트 암호로 서비스 계정을 생성하기 때문에) pocketbase에서 약간의 작업을 수행할 수도 있습니다.
1 - Google 서비스 계정 설정
for this tutorial i used
-
http://localhost:3000/redirect as the redirect url and
-
http://localhost:3000 for authorised origins
official docs
2 - app.tsx에 리디렉션 경로 추가
react-router-dom 을 사용하고 있으므로 App.tsx에서 클라이언트 경로를 정의합니다.
import { useState } from 'react'
import { Query, useQuery } from 'react-query';
import { Routes, Route, BrowserRouter } from "react-router-dom";
import './App.css'
import { About } from './components/about/About';
import { Login } from './components/auth/Login';
import { Protected } from './components/auth/Protected';
import { Redirect } from './components/auth/Redirect';
import { UserType } from './components/auth/types';
import { Home } from './components/home/Home';
import { Toolbar } from './components/toolbar/Toolbar';
import { client } from './pb/config';
import { LoadingShimmer } from './components/Shared/LoadingShimmer';
function App() {
const getUser = async()=>{
return await client.authStore.model
}
const userQuery = useQuery(["user"],getUser);
console.log("user query App.tsx==== ", userQuery)
// console.log("client authstore",client.authStore)
const user = userQuery.data
if(userQuery.isFetching || userQuery.isFetching){
return <LoadingShimmer/>
}
return (
<div
className="h-screen w-screen scroll-bar flex-col-center
dark-styles transition duration-500 overflow-x-hidden "
>
<BrowserRouter >
<div className="fixed top-[0px] w-[100%] z-40 p-1">
<Toolbar />
</div>
<div className="w-full h-full mt-12 ">
<Routes>
<Route
path="/"
element={
<Protected user={user}>
<Home />
</Protected>
}
/>
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login user={user}/>} />
<Route path="/redirect" element={<Redirect user=
{user}/>} />
</Routes>
</div>
</BrowserRouter>
</div>
);
}
export default App
리디렉션 및 로그인 구성 요소를 만듭니다.
리디렉션.tsx
import { User, Admin } from 'pocketbase';
import React, { useEffect } from 'react'
import { useQueryClient } from 'react-query';
import { Navigate, useNavigate, useSearchParams } from 'react-router-dom';
import { client } from '../../pb/config';
import { LoadingShimmer } from '../Shared/loading/LoadingShimmer';
interface RedirectProps {
user?: User | Admin | null
}
export const Redirect: React.FC<RedirectProps> = ({user}) => {
const [loading, setLoading] = React.useState(true)
const queryClient = useQueryClient()
const navigate = useNavigate()
const [searchParams] = useSearchParams();
const code = searchParams.get('code') as string
const local_prov = JSON.parse(localStorage.getItem('provider') as string)
// this hasto match what you orovided in the oauth provider , in tis case google
let redirectUrl = 'http://localhost:3000/redirect'
useEffect(()=>{
if (local_prov.state !== searchParams.get("state")) {
const url = 'http://localhost:3000/login'
if (typeof window !== 'undefined') {
window.location.href = url;
}
}
else {
client.users.authViaOAuth2(
local_prov.name,
code,
local_prov.codeVerifier,
redirectUrl
)
.then((response) => {
// console.log("authentication data === ", response)
// udating te user rofile field in pocket base with custome data from your
// oauth provider in this case the avatarUrl and name
client.records.update('profiles', response.user.profile?.id as string, {
name: response.meta.name,
avatarUrl: response.meta.avatarUrl,
}).then((res) => {
// console.log(" successfully updated profi;e", res)
}).catch((e) => {
console.log("error updating profile == ", e)
})
setLoading(false)
// console.log("client modal after logg == ", client.authStore.model)
queryClient.setQueryData(['user'], client.authStore.model)
navigate('/')
}).catch((e) => {
console.log("error logging in with provider == ", e)
})
}
},[])
if (user) {
return <Navigate to="/" replace />;
}
return (
<div className='w-full h-full '>
{loading ? <LoadingShimmer/>:null}
</div>
);
}
로그인.tsx
import React from "react";
import { providers } from "../../pb/config";
import { useNavigate } from 'react-router-dom';
import { Admin, User } from "pocketbase";
interface LoginProps {
user?: User | Admin | null
}
interface ProvType{
name: string
state: string
codeVerifier: string
codeChallenge: string
codeChallengeMethod: string
authUrl: string
}
export const Login: React.FC<
LoginProps
> = ({user}) => {
const provs = providers.authProviders;
const navigate = useNavigate()
// console.log("user in Login.tsx == ",user)
if(user?.email){
navigate('/')
}
const startLogin = (prov:ProvType) => { localStorage.setItem("provider",JSON.stringify(prov));
const redirectUrl = "http://localhost:3000/redirect";
const url = prov.authUrl + redirectUrl;
// console.log("prov in button === ", prov)
// console.log("combined url ==== >>>>>> ",url)
if (typeof window !== "undefined") {
window.location.href = url;
}
};
return (
<div className="w-full h-full flex-center-col">
<div className="text-3xl font-bold ">
LOGIN
</div>
{provs &&
provs?.map((item:any) => {
return (
<button
className="p-2 bg-purple-600"
key={item.name}
onClick={() => startLogin(item)}>{item.name}</button>
);
})}
</div>
);
};
보호됨.tsx
import { Admin, User } from 'pocketbase';
import React, { ReactNode } from 'react'
import { Navigate } from 'react-router-dom';
interface ProtectedProps {
user?: User | Admin | null
children:ReactNode
}
export const Protected: React.FC<ProtectedProps> = ({user,children}) => {
if(!user?.email){
return <Navigate to={'/login'} />
}
return (
<div className='h-full w-full'>
{children}
</div>
);
}
full code
Reference
이 문제에 관하여(pocketbase + google-oauth + react-router + react-query로 반응 인증), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/tigawanna/react-authentication-with-pocketbase-google-oauth-react-router-react-query-a5j
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
for this tutorial i used
- http://localhost:3000/redirect as the redirect url and
- http://localhost:3000 for authorised origins
import { useState } from 'react'
import { Query, useQuery } from 'react-query';
import { Routes, Route, BrowserRouter } from "react-router-dom";
import './App.css'
import { About } from './components/about/About';
import { Login } from './components/auth/Login';
import { Protected } from './components/auth/Protected';
import { Redirect } from './components/auth/Redirect';
import { UserType } from './components/auth/types';
import { Home } from './components/home/Home';
import { Toolbar } from './components/toolbar/Toolbar';
import { client } from './pb/config';
import { LoadingShimmer } from './components/Shared/LoadingShimmer';
function App() {
const getUser = async()=>{
return await client.authStore.model
}
const userQuery = useQuery(["user"],getUser);
console.log("user query App.tsx==== ", userQuery)
// console.log("client authstore",client.authStore)
const user = userQuery.data
if(userQuery.isFetching || userQuery.isFetching){
return <LoadingShimmer/>
}
return (
<div
className="h-screen w-screen scroll-bar flex-col-center
dark-styles transition duration-500 overflow-x-hidden "
>
<BrowserRouter >
<div className="fixed top-[0px] w-[100%] z-40 p-1">
<Toolbar />
</div>
<div className="w-full h-full mt-12 ">
<Routes>
<Route
path="/"
element={
<Protected user={user}>
<Home />
</Protected>
}
/>
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login user={user}/>} />
<Route path="/redirect" element={<Redirect user=
{user}/>} />
</Routes>
</div>
</BrowserRouter>
</div>
);
}
export default App
import { User, Admin } from 'pocketbase';
import React, { useEffect } from 'react'
import { useQueryClient } from 'react-query';
import { Navigate, useNavigate, useSearchParams } from 'react-router-dom';
import { client } from '../../pb/config';
import { LoadingShimmer } from '../Shared/loading/LoadingShimmer';
interface RedirectProps {
user?: User | Admin | null
}
export const Redirect: React.FC<RedirectProps> = ({user}) => {
const [loading, setLoading] = React.useState(true)
const queryClient = useQueryClient()
const navigate = useNavigate()
const [searchParams] = useSearchParams();
const code = searchParams.get('code') as string
const local_prov = JSON.parse(localStorage.getItem('provider') as string)
// this hasto match what you orovided in the oauth provider , in tis case google
let redirectUrl = 'http://localhost:3000/redirect'
useEffect(()=>{
if (local_prov.state !== searchParams.get("state")) {
const url = 'http://localhost:3000/login'
if (typeof window !== 'undefined') {
window.location.href = url;
}
}
else {
client.users.authViaOAuth2(
local_prov.name,
code,
local_prov.codeVerifier,
redirectUrl
)
.then((response) => {
// console.log("authentication data === ", response)
// udating te user rofile field in pocket base with custome data from your
// oauth provider in this case the avatarUrl and name
client.records.update('profiles', response.user.profile?.id as string, {
name: response.meta.name,
avatarUrl: response.meta.avatarUrl,
}).then((res) => {
// console.log(" successfully updated profi;e", res)
}).catch((e) => {
console.log("error updating profile == ", e)
})
setLoading(false)
// console.log("client modal after logg == ", client.authStore.model)
queryClient.setQueryData(['user'], client.authStore.model)
navigate('/')
}).catch((e) => {
console.log("error logging in with provider == ", e)
})
}
},[])
if (user) {
return <Navigate to="/" replace />;
}
return (
<div className='w-full h-full '>
{loading ? <LoadingShimmer/>:null}
</div>
);
}
import React from "react";
import { providers } from "../../pb/config";
import { useNavigate } from 'react-router-dom';
import { Admin, User } from "pocketbase";
interface LoginProps {
user?: User | Admin | null
}
interface ProvType{
name: string
state: string
codeVerifier: string
codeChallenge: string
codeChallengeMethod: string
authUrl: string
}
export const Login: React.FC<
LoginProps
> = ({user}) => {
const provs = providers.authProviders;
const navigate = useNavigate()
// console.log("user in Login.tsx == ",user)
if(user?.email){
navigate('/')
}
const startLogin = (prov:ProvType) => { localStorage.setItem("provider",JSON.stringify(prov));
const redirectUrl = "http://localhost:3000/redirect";
const url = prov.authUrl + redirectUrl;
// console.log("prov in button === ", prov)
// console.log("combined url ==== >>>>>> ",url)
if (typeof window !== "undefined") {
window.location.href = url;
}
};
return (
<div className="w-full h-full flex-center-col">
<div className="text-3xl font-bold ">
LOGIN
</div>
{provs &&
provs?.map((item:any) => {
return (
<button
className="p-2 bg-purple-600"
key={item.name}
onClick={() => startLogin(item)}>{item.name}</button>
);
})}
</div>
);
};
import { Admin, User } from 'pocketbase';
import React, { ReactNode } from 'react'
import { Navigate } from 'react-router-dom';
interface ProtectedProps {
user?: User | Admin | null
children:ReactNode
}
export const Protected: React.FC<ProtectedProps> = ({user,children}) => {
if(!user?.email){
return <Navigate to={'/login'} />
}
return (
<div className='h-full w-full'>
{children}
</div>
);
}
Reference
이 문제에 관하여(pocketbase + google-oauth + react-router + react-query로 반응 인증), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tigawanna/react-authentication-with-pocketbase-google-oauth-react-router-react-query-a5j텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)