first commit

This commit is contained in:
René Preuß
2023-02-18 14:27:55 +01:00
commit 47b0bf4ec9
23 changed files with 10379 additions and 0 deletions

65
src/module.ts Normal file
View File

@@ -0,0 +1,65 @@
import {addImportsDir, addPlugin, createResolver, defineNuxtModule} from '@nuxt/kit'
import defu from "defu";
// Module options TypeScript interface definition
export interface ModuleOptions {
redirect: {
login: string,
logout: string,
callback: string,
home: string
},
endpoints: {
authorization: string,
userInfo: string,
logout: string
},
clientId: string,
scope: string[]
}
const defaults: ModuleOptions = {
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
},
endpoints: {
authorization: 'https://accounts.bitinflow.com/oauth/authorize',
userInfo: `https://accounts.bitinflow.com/api/v3/user`,
logout: 'https://accounts.bitinflow.com/logout'
},
clientId: 'please-set-client-id',
scope: ['user:read']
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: '@bitinflow/nuxt-oauth',
configKey: 'oauth'
},
defaults,
setup (moduleOptions, nuxt) {
const resolver = createResolver(import.meta.url)
const options = defu(moduleOptions, {
...defaults
})
// Set up runtime configuration
nuxt.options.runtimeConfig = nuxt.options.runtimeConfig || { public: {} }
nuxt.options.runtimeConfig.oauth = defu(nuxt.options.runtimeConfig.oauth, {
...options
})
nuxt.options.runtimeConfig.public.oauth = defu(nuxt.options.runtimeConfig.public.oauth, {
...options
})
// Do not add the extension since the `.ts` will be transpiled to `.mjs` after `npm run prepack`
addPlugin(resolver.resolve('./runtime/plugin'))
const composables = resolver.resolve('./runtime/composables')
addImportsDir(composables)
}
})

View File

@@ -0,0 +1,68 @@
import {CookieRef, navigateTo, useCookie, useRuntimeConfig} from "#app";
import {ModuleOptions} from "../../module";
declare interface ComposableOptions {
fetchUserOnInitialization: boolean
}
export default async (options: ComposableOptions = {
fetchUserOnInitialization: false
}) => {
const user: CookieRef<any> = useCookie('oauth_user')
const accessToken: CookieRef<any> = useCookie('oauth_access_token')
const authConfig = useRuntimeConfig().public.oauth as ModuleOptions;
const fetchUser = async () => {
try {
const response = await fetch(authConfig.endpoints.userInfo, {
headers: {
Accept: 'application/json',
Authorization: `${accessToken.value.tokenType} ${accessToken.value.token}`
}
});
user.value = response.ok
? await response.json()
: null;
} catch (e) {
user.value = null;
}
}
const signIn = async () => {
// create oauth authorization url
const params = new URLSearchParams({
client_id: authConfig.clientId,
redirect_uri: window.location.origin + authConfig.redirect.callback,
response_type: 'token',
scope: authConfig.scope.join(' ')
})
window.location.href = `${authConfig.endpoints.authorization}?${params.toString()}`
};
const signOut = async () => {
accessToken.value = null;
user.value = null;
return navigateTo('/')
}
const setBearer = async (token: string, tokenType: string, expires: number) => {
accessToken.value = {token, tokenType, expiresAt: Date.now() + expires * 1000};
await fetchUser()
}
// Initialize the user if the option is set to true
if (options.fetchUserOnInitialization) {
await fetchUser()
}
return {
user,
signIn,
signOut,
setBearer,
authConfig
}
}

35
src/runtime/plugin.ts Normal file
View File

@@ -0,0 +1,35 @@
import {addRouteMiddleware, defineNuxtPlugin, navigateTo} from '#app'
import useAuth from "./composables/useAuth"
export default defineNuxtPlugin(() => {
addRouteMiddleware('auth', async (to) => {
const {user, authConfig, setBearer} = await useAuth()
if (to.path === authConfig.redirect.callback) {
const params = new URLSearchParams(to.hash.substring(1))
if (params.has('access_token')) {
const token = params.get('access_token') as string;
const tokenType = params.get('token_type') as string;
const expires = params.get('expires_in') as string;
await setBearer(token, tokenType, parseInt(expires));
return navigateTo(authConfig.redirect.home)
}
return
}
if (user.value === undefined) {
return navigateTo(authConfig.redirect.login)
}
})
addRouteMiddleware('guest', async () => {
const {user, authConfig} = await useAuth()
if (user.value !== undefined) {
return navigateTo(authConfig.redirect.home)
}
})
})