액세스를 위임하여주는 개방형 표준 인가 프로토콜이다.
다양한 플랫폼 환경에서 권한을 부여해 줄 수 있다.
프론트엔드 단에서는 인가 요청을 하여 인가 코드를 발급하고 해당 인가 코드를 백엔드로 넘겨주면 된다.
서버에서는 사용자가 로그인 하면 사용자와 1:1 매핑이 되도록 access token과 refresh token 값을 DB에 저장하고 클라이언트에 두 token 모두 내려준다.
클라이언트는 쿠키에 두 token 값을 저장한다.
API를 통신할 때에, 클라이언트는 access token 값을 header에 담아 전송한다.
서버에서 access token이 만료되었으면 클라이언트에 401 에러를 보낸다.
클라이언트는 401 에러를 받으면 refresh token을 header에 담아 보낸다.
서버는 받은 refresh token을 검증한다.
6-1. refresh token이 만료되었으면 401에러를 보낸다. 클라이언트는 401에러를 받으면 로그인 페이지로 보낸다.
6-2. refresh token이 만료되지 않았으면 새로운 access token과 refresh token을 발급한 후 클라이언트에 보낸다.
access token은 수명을 5~30분 정도로 짧게 가져가고, refresh token은 짧게는 3일에서 길게는 1년까지 길게 가져간다.
<GoogleOAuthProvider clientId={clientId}> // 구글 클라우드 플랫폼에서 발급받은 client Id 넣기
<Paper variant='outlined' onClick={()=>login()}>
<Typography>Google Login</Typography>
</Paper>
</GoogleOAuthProvider>
type loginPayload = {
authCode: string;
}
const login = useGoogleLogin({
onSuccess: async tokenResponse => {
const payload: loginPayload = {
authCode: tokenResponse.code
}
mutate(payload) // api 통신 함수
},
onError: (errorResponse: unknown) => {
console.error(errorResponse);
},
flow: "auth-code",
});
export const getApi = (apiEndPoint: string, api: string) => {
return fetch(apiEndPoint + api, {
headers: {
"Gauth": getCookie('access')
}
})
}
export const postApi = (apiEndPoint: string, api: string, payload: any) => {
return fetch(apiEndPoint + api, {
method: 'POST',
headers : { 'Content-Type' : 'application/json',
'Gauth': getCookie('access') },
body: JSON.stringify(payload)
})
}
export const putApi = (apiEndPoint: string, api: string, payload: any) => {
return fetch(apiEndPoint + api, {
method: 'PUT',
headers : { 'Content-Type' : 'application/json',
'Gauth': getCookie('access') },
body: JSON.stringify(payload)
})
}
export const deleteApi = (apiEndPoint: string, api: string) => {
return fetch(apiEndPoint + api, {
method: 'DELETE',
headers : { 'Content-Type' : 'application/json',
'Gauth': getCookie('access') }
})
}
export const refreshApi = (apiEndPoint: string, notify: Function, navigate: Function) => {
return fetch(`${apiEndPoint}/api/update/token`
, {
headers: {
'Refresh' : getCookie('refresh')
}
}
).then(response => {
if (response.status === 401) {
navigate('/login')
notify('Login time has expired')
throw new Error('로그아웃')
}
else if (response.status === 200) {
let jwtToken: string | null = response.headers.get('Gauth')
let refreshToken: string | null = response.headers.get('RefreshToken')
if (jwtToken) {
setCookie('access', jwtToken)
}
if (refreshToken) {
setCookie('refresh', refreshToken)
}
}
})
}