chore: initial commit
This commit is contained in:
105
utils/authentication/Authentication.ts
Normal file
105
utils/authentication/Authentication.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import axios, { AxiosInstance } from 'axios'
|
||||
import { io, Socket } from 'socket.io-client'
|
||||
|
||||
import { API_URL } from 'utils/api'
|
||||
import { cookies } from 'utils/cookies'
|
||||
import { Tokens } from '.'
|
||||
import { fetchRefreshToken } from './authenticationFromServerSide'
|
||||
|
||||
export class Authentication {
|
||||
public tokens: Tokens
|
||||
public accessTokenAge: number
|
||||
public socket: Socket
|
||||
public api: AxiosInstance
|
||||
|
||||
constructor (tokens: Tokens) {
|
||||
this.tokens = tokens
|
||||
this.accessTokenAge = Date.now()
|
||||
this.socket = io(API_URL, {
|
||||
auth: { token: `Bearer ${tokens.accessToken}` }
|
||||
})
|
||||
this.socket.on('connect_error', (error) => {
|
||||
if (error.message.startsWith('Unauthorized')) {
|
||||
fetchRefreshToken(this.tokens.refreshToken)
|
||||
.then(({ accessToken }) => {
|
||||
this.setAccessToken(accessToken)
|
||||
})
|
||||
.catch(async () => {
|
||||
this.signout()
|
||||
return await Promise.reject(error)
|
||||
})
|
||||
}
|
||||
})
|
||||
this.api = axios.create({
|
||||
baseURL: API_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
this.api.interceptors.request.use(
|
||||
async (config) => {
|
||||
const isValidAccessToken =
|
||||
this.accessTokenAge + tokens.expiresIn > Date.now()
|
||||
if (!isValidAccessToken) {
|
||||
const { accessToken } = await fetchRefreshToken(
|
||||
this.tokens.refreshToken
|
||||
)
|
||||
this.setAccessToken(accessToken)
|
||||
}
|
||||
config.headers.Authorization = `${this.tokens.type} ${this.tokens.accessToken}`
|
||||
return config
|
||||
},
|
||||
async (error) => {
|
||||
this.signout()
|
||||
return await Promise.reject(error)
|
||||
}
|
||||
)
|
||||
this.api.interceptors.response.use(
|
||||
(response) => {
|
||||
return response
|
||||
},
|
||||
async (error) => {
|
||||
if (error.response.status !== 403 || (error.config._retry as boolean)) {
|
||||
return await Promise.reject(error)
|
||||
}
|
||||
error.config._retry = true
|
||||
try {
|
||||
const { accessToken } = await fetchRefreshToken(
|
||||
this.tokens.refreshToken
|
||||
)
|
||||
this.setAccessToken(accessToken)
|
||||
error.response.config.headers.Authorization = `${this.tokens.type} ${this.tokens.accessToken}`
|
||||
return await this.api.request(error.response.config)
|
||||
} catch {
|
||||
this.signout()
|
||||
return await Promise.reject(error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public setAccessToken (accessToken: string): void {
|
||||
this.tokens.accessToken = accessToken
|
||||
this.accessTokenAge = Date.now()
|
||||
const token = `${this.tokens.type} ${this.tokens.accessToken}`
|
||||
if (typeof this.socket.auth !== 'function') {
|
||||
this.socket.auth.token = token
|
||||
}
|
||||
}
|
||||
|
||||
public signout (): void {
|
||||
cookies.remove('refreshToken')
|
||||
window.location.href = '/authentication/signin'
|
||||
}
|
||||
|
||||
public async signoutServerSide (): Promise<void> {
|
||||
await this.api.post('/users/signout', {
|
||||
refreshToken: this.tokens.refreshToken
|
||||
})
|
||||
this.signout()
|
||||
}
|
||||
|
||||
public signin (): void {
|
||||
cookies.set('refreshToken', this.tokens.refreshToken)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user