Skip to content

Commit

Permalink
Merge pull request #8 from KhaledAlMana/main
Browse files Browse the repository at this point in the history
  • Loading branch information
KhaledAlMana authored Dec 18, 2022
2 parents 4e0e046 + af9f2eb commit db0dab4
Show file tree
Hide file tree
Showing 16 changed files with 111 additions and 51 deletions.
7 changes: 5 additions & 2 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ export default defineNuxtConfig({
clientSecret: 'secret',
callbackUrl: '',
scope: [
'openid',
'email',
'profile'
'profile',
// 'address'
]
},
config: {
response_type: 'id_token',
debug: true,
response_type: 'code',
secret: 'oidc._sessionid',
cookie: { loginName: '' },
cookiePrefix: 'oidc._',
Expand Down
11 changes: 11 additions & 0 deletions playground/pages/[...slug].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<div>
<NavBar />
<main class="container">
<h1> 401 Unauthenticated</h1>
</main>
</div>
</template>

<script lang="ts" >
</script>
1 change: 1 addition & 0 deletions playground/pages/public.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<div>
<NavBar />
<main class="container">
<h1> Public Page </h1>
<b-alert show variant="success">
You should see this page without need to authentication!
</b-alert>
Expand Down
10 changes: 8 additions & 2 deletions playground/pages/secure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
<div>
<NavBar />
<main class="container">
<h1> Secure Page </h1>
<b-alert show variant="success">
You should see this page without need to authentication!
Secured content
You should see this page <b> only if authenticated!</b>
</b-alert>
</main>
</div>
</template>

<script lang="ts">
<script lang="ts" setup>
const { $oidc } = useNuxtApp()
if(!$oidc.isLoggedIn) {
navigateTo('/401');
}
</script>
19 changes: 12 additions & 7 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { fileURLToPath } from 'url'
import { defineNuxtModule, addPlugin, resolveModule, createResolver } from '@nuxt/kit'
import { defineNuxtModule, addPlugin, resolveModule, createResolver } from '@nuxt/kit';
import defu from 'defu'
import { name, version } from '../package.json'
import { logger } from './runtime/utils/logger';


export type CookieSerializeOptions = {
domain?: string | undefined;
Expand Down Expand Up @@ -35,6 +37,7 @@ export type Config = {
cookieFlags?: {
[key: string]: CookieSerializeOptions,
}
debug?: boolean | undefined,
}

export interface ModuleOptions {
Expand All @@ -61,13 +64,11 @@ export default defineNuxtModule<ModuleOptions>({
clientSecret: '',
callbackUrl: '',
scope: [
'email',
'profile',
'address'
]
},
// express-session configuration
config: {
debug: false,
secret: 'oidc._sessionid', // process.env.OIDC_SESSION_SECRET
cookie: {},
cookiePrefix: 'oidc._',
Expand All @@ -80,8 +81,12 @@ export default defineNuxtModule<ModuleOptions>({
cookieFlags: {}
}
},
setup (options, nuxt) {
// console.log(options.op)
setup(options, nuxt) {
logger.level = options.config.debug == true ? 5 : 0 // 4 = debug, 5 = trace
logger.info('[DEBUG MODE]: ', options.config.debug);
logger.debug('[WITHOUT ENV VARS] options:', options);


const { resolve } = createResolver(import.meta.url)
const resolveRuntimeModule = (path: string) => resolveModule(path, { paths: resolve('./runtime') })

Expand Down Expand Up @@ -144,4 +149,4 @@ export default defineNuxtModule<ModuleOptions>({
addPlugin(resolve(runtimeDir, 'plugin'))
}
}
})
})
18 changes: 11 additions & 7 deletions src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Storage, StorageOptions } from './storage'
import { isUnset, isSet } from './utils/utils'
import { encrypt, decrypt } from './utils/encrypt'
import { useState, useFetch, useRuntimeConfig, useCookie } from '#imports'
import { logger } from '@nuxt/kit'

interface UseState {
user: any,
Expand All @@ -14,7 +15,7 @@ class Oidc {
private $useState: any // State: Nuxt.useState (share state in all nuxt pages and components) https://v3.nuxtjs.org/guide/features/state-management
public $storage: Storage // LocalStorage: Browser.localStorage (share state in all sites, use in page refresh.)

constructor () {
constructor() {
this.state = { user: {}, isLoggedIn: false }

this.$useState = useState<UseState>('useState', () => { return { user: {}, isLoggedIn: false } })
Expand All @@ -29,7 +30,7 @@ class Oidc {
this.$storage = storage
}

get user () {
get user() {
const userInfoState = this.$useState.value.user
const userInfoLS = this.$storage.getUserInfo()
if ((isUnset(userInfoState))) {
Expand All @@ -42,14 +43,14 @@ class Oidc {
// return this.state.user // not auto update
}

get isLoggedIn () {
get isLoggedIn() {
const isLoggedIn = this.$useState.value.isLoggedIn
const isLoggedInLS = this.$storage.isLoggedIn()
// console.log('isLoggedIn', isLoggedIn, isLoggedInLS)
return isLoggedIn || isLoggedInLS
}

setUser (user: any) {
setUser(user: any) {
this.state.user = user
this.state.isLoggedIn = Object.keys(user).length > 0

Expand All @@ -59,7 +60,7 @@ class Oidc {
this.$storage.setUserInfo(user)
}

async fetchUser () {
async fetchUser() {
try {
if (process.server) {
console.log('serve-render: fetchUser from cookie.')
Expand Down Expand Up @@ -93,7 +94,7 @@ class Oidc {
}
}

login (redirect = '/') {
login(redirect = '/') {
if (process.client) {
const params = new URLSearchParams({ redirect })
const toStr = '/oidc/login' // + params.toString()
Expand All @@ -102,7 +103,7 @@ class Oidc {
}
}

logout () {
logout() {
// TODO clear user info when accessToken expired.
if (process.client) {
this.$useState.value.user = {}
Expand All @@ -115,8 +116,11 @@ class Oidc {
}

export default defineNuxtPlugin((nuxtApp) => {
// TODO: enable consola debug mode here instead of console.log
console.log('--- Nuxt plugin: nuxt-openid-connect!')
const oidc = new Oidc()
nuxtApp.provide('oidc', oidc)
// console.log('--- Nuxt plugin: DEBUG MODE:' + useNuxtApp().ssrContext?.runtimeConfig.openidConnect.config.debug);

oidc.fetchUser() // render both from server and client.
})
11 changes: 7 additions & 4 deletions src/runtime/server/routes/oidc/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { defineEventHandler, getCookie, setCookie } from 'h3'
import { initClient } from '../../../utils/issueclient'
import { encrypt } from '../../../utils/encrypt'
import { useRuntimeConfig } from '#imports'
import { logger } from '../../../utils/logger'

export default defineEventHandler(async (event) => {
console.log('oidc/callback calling')
logger.debug('[CALLBACK]: oidc/callback calling')
const { op, config } = useRuntimeConfig().openidConnect
const sessionid = getCookie(event, config.secret)
const req = event.node.req
Expand All @@ -14,19 +15,21 @@ export default defineEventHandler(async (event) => {
const callBackUrl = op.callbackUrl.replace('cbt', 'callback')

if (params.access_token) {
logger.debug('[CALLBACK]: has access_token in params')
await getUserInfo(params.access_token)
} else if (params.code) {
logger.debug('[CALLBACK]: has code in params')
const tokenSet = await issueClient.callback(callBackUrl, params, { nonce: sessionid })
if (tokenSet.access_token) {
await getUserInfo(tokenSet.access_token)
}
} else {
console.log('empty callback')
logger.debug('[CALLBACK]: empty callback')
}
res.writeHead(302, { Location: '/' })
res.end()

async function getUserInfo (accessToken: string) {
async function getUserInfo(accessToken: string) {
try {
const userinfo = await issueClient.userinfo(accessToken)
setCookie(event, config.cookiePrefix + 'access_token', accessToken, {
Expand All @@ -45,7 +48,7 @@ export default defineEventHandler(async (event) => {
const encryptedText = await encrypt(JSON.stringify(userinfo), config)
setCookie(event, config.cookiePrefix + 'user_info', encryptedText, { ...config.cookieFlags['user_info' as keyof typeof config.cookieFlags] })
} catch (err) {
console.log(err)
logger.error("[CALLBACK]: " + err)
}
}
})
5 changes: 3 additions & 2 deletions src/runtime/server/routes/oidc/cbt.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { defineEventHandler, setCookie, getCookie } from 'h3'
import { CBT_PAGE_TEMPATE } from '../../../utils/template'
import { useRuntimeConfig } from '#imports'
import { logger } from '@nuxt/kit'

export default defineEventHandler((event) => {
console.log('oidc/cbt calling')
logger.debug('[CBT]: oidc/cbt calling')
const { config } = useRuntimeConfig().openidConnect
const res = event.res
const html = CBT_PAGE_TEMPATE

const sessionkey = config.secret
const sessionid = getCookie(event, sessionkey)
// console.log(sessionid)
// logger.debug('[CBT]:' + sessionid)
/* setCookie(event, sessionkey, sessionid, {
maxAge: 24 * 60 * 60 // oneday
}) */
Expand Down
11 changes: 6 additions & 5 deletions src/runtime/server/routes/oidc/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { v4 as uuidv4 } from 'uuid'

import { initClient } from '../../../utils/issueclient'
import { useRuntimeConfig } from '#imports'
import { logger } from '../../../utils/logger'

export default defineEventHandler(async (event) => {
console.log('oidc/login calling')
logger.info('[Login]: oidc/login calling')
const { op, config } = useRuntimeConfig().openidConnect

const req = event.req
Expand All @@ -14,12 +15,12 @@ export default defineEventHandler(async (event) => {
const sessionkey = config.secret
let sessionid = getCookie(event, config.secret)
if (!sessionid) {
// console.log('regenerate sessionid')
logger.trace('[Login]: regenerate sessionid')
sessionid = uuidv4()
}

const callbackUrl = (op.callbackUrl && op.callbackUrl.length > 0) ? op.callbackUrl : 'http://' + req.headers.host + '/oidc/cbt'
// console.log('cabackurl:', callbackUrl, op.callbackUrl)
logger.trace('[Login]: cabackurl: ', callbackUrl, op.callbackUrl)

const parameters = {
redirect_uri: callbackUrl,
Expand All @@ -28,9 +29,9 @@ export default defineEventHandler(async (event) => {
scope: op.scope.join(' ') // 'openid' will be added by default
}
const authUrl = issueClient.authorizationUrl(parameters)
// console.log(authUrl)
logger.trace('[Login]: Auth Url: ' + authUrl)

console.log(sessionid)
logger.debug('[Login]: sessionid: ' + sessionid)
if (sessionid) {
setCookie(event, sessionkey, sessionid, {
maxAge: config.cookieMaxAge,
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/server/routes/oidc/logout.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { getCookie, deleteCookie, defineEventHandler } from 'h3'
import { useRuntimeConfig } from '#imports'
import { logger } from '../../../utils/logger'

export default defineEventHandler((event) => {
const res = event.res
console.log('oidc/logout calling')
logger.log('[LOGOUT]: oidc/logout calling')

const { config } = useRuntimeConfig().openidConnect
deleteCookie(event, config.secret)
Expand Down
9 changes: 5 additions & 4 deletions src/runtime/server/routes/oidc/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { getCookie, deleteCookie, defineEventHandler } from 'h3'
import { initClient } from '../../../utils/issueclient'
import { encrypt, decrypt } from '../../../utils/encrypt'
import { useRuntimeConfig } from '#imports'
import { logger } from '../../../utils/logger'

export default defineEventHandler(async (event) => {
const { config, op } = useRuntimeConfig().openidConnect
console.log('oidc/user calling')
// console.log(req.headers.cookie)
logger.debug('[USER]: oidc/user calling')
logger.trace('[USER]: ' + event.req.headers.cookie)

const sessionid = getCookie(event, config.secret)
const accesstoken = getCookie(event, config.cookiePrefix + 'access_token')
Expand All @@ -30,7 +31,7 @@ export default defineEventHandler(async (event) => {
}
return userinfo
} catch (err) {
console.log(err)
logger.error('[USER]: ' + err)
deleteCookie(event, config.secret)
deleteCookie(event, config.cookiePrefix + 'access_token')
deleteCookie(event, config.cookiePrefix + 'user_info')
Expand All @@ -43,7 +44,7 @@ export default defineEventHandler(async (event) => {
return {}
}
} else {
console.log('empty accesstoken for access userinfo')
logger.debug('[USER]: empty accesstoken for access userinfo')
return {}
}
})
Loading

0 comments on commit db0dab4

Please sign in to comment.