-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: 0x73746F66 <[email protected]>
- Loading branch information
0x73746F66
committed
Jun 11, 2024
1 parent
fffee16
commit 8180769
Showing
4 changed files
with
90 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export const onRequestGet = async context => { | ||
if ( | ||
context.params?.email && | ||
context.params?.hash | ||
) { | ||
console.log('email', context.params.email) | ||
|
||
|
||
} | ||
return new Response.json({ 'err': 'OAuth authorization code not provided' }) | ||
} | ||
|
||
async function pbkdf2Verify(key, password, hashBits = 512) { | ||
let compositeStr = null // composite key is salt, iteration count, and derived key | ||
try { compositeStr = atob(key) } catch (e) { throw new Error('Invalid key') } // decode from base64 | ||
const version = compositeStr.slice(0, 3) // 3 bytes | ||
const saltStr = compositeStr.slice(3, 19) // 16 bytes (128 bits) | ||
const iterStr = compositeStr.slice(19, 22) // 3 bytes | ||
const keyStr = compositeStr.slice(22) // remaining bytes | ||
if (version != 'v01') { | ||
throw new Error('Invalid key') | ||
} | ||
// -- recover salt & iterations from stored (composite) key | ||
const saltUint8 = new Uint8Array(saltStr.match(/./g).map(ch => ch.charCodeAt(0))) // salt as Uint8Array | ||
// note: cannot use TextEncoder().encode(saltStr) as it generates UTF-8 | ||
const iterHex = iterStr.match(/./g).map(ch => ch.charCodeAt(0).toString(16)).join('') // iter’n count as hex | ||
const iterations = parseInt(iterHex, 16) // iter’ns | ||
// -- generate new key from stored salt & iterations and supplied password | ||
const pwUtf8 = new TextEncoder().encode(password) // encode pw as UTF-8 | ||
const pwKey = await crypto.subtle.importKey('raw', pwUtf8, 'PBKDF2', false, ['deriveBits']) // create pw key | ||
const params = { name: 'PBKDF2', hash: `SHA-${hashBits}`, salt: saltUint8, iterations: iterations } // pbkdf params | ||
const keyBuffer = await crypto.subtle.deriveBits(params, pwKey, hashBits) // derive key | ||
const keyArray = Array.from(new Uint8Array(keyBuffer)) // key as byte array | ||
const keyStrNew = keyArray.map(byte => String.fromCharCode(byte)).join('') // key as string | ||
return keyStrNew === keyStr // test if newly generated key matches stored key | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
export const onRequestGet = async context => { | ||
if ( | ||
context.params?.org && | ||
context.params?.email && | ||
context.params?.hash | ||
) { | ||
console.log('org', context.params.org) | ||
// const kid = crypto.randomUUID() | ||
const { results } = await context.env.trivial_triage.prepare( | ||
"SELECT * FROM members WHERE email = ?" | ||
) | ||
.bind(context.params.email) | ||
.all() | ||
return Response.json(results) | ||
} | ||
return new Response.json({ 'err': 'OAuth authorization code not provided' }) | ||
} | ||
|
||
async function pbkdf2(password, iterations = 1e6, hashBits = 512) { | ||
const pwUtf8 = new TextEncoder().encode(password) // encode pw as UTF-8 | ||
const pwKey = await crypto.subtle.importKey('raw', pwUtf8, 'PBKDF2', false, ['deriveBits']) // create pw key | ||
const saltUint8 = crypto.getRandomValues(new Uint8Array(16)) // get random salt | ||
const params = { name: 'PBKDF2', hash: `SHA-${hashBits}`, salt: saltUint8, iterations: iterations } // pbkdf2 params | ||
const keyBuffer = await crypto.subtle.deriveBits(params, pwKey, hashBits) // derive key | ||
const keyArray = Array.from(new Uint8Array(keyBuffer)) // key as byte array | ||
const saltArray = Array.from(new Uint8Array(saltUint8)) // salt as byte array | ||
const iterHex = ('000000' + iterations.toString(16)).slice(-6) // iter’n count as hex | ||
const iterArray = iterHex.match(/.{2}/g).map(byte => parseInt(byte, 16)) // iter’ns as byte array | ||
const compositeArray = [].concat(saltArray, iterArray, keyArray) // combined array | ||
const compositeStr = compositeArray.map(byte => String.fromCharCode(byte)).join('') // combined as string | ||
return btoa('v01' + compositeStr) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,12 @@ | |
import IconTrivialSecurity from '@images/IconTrivialSecurity.vue' | ||
import { useVuelidate } from '@vuelidate/core' | ||
import { email, required } from '@vuelidate/validators' | ||
import { WordArray } from 'crypto-es/lib/core' | ||
import { PBKDF2 } from 'crypto-es/lib/pbkdf2' | ||
import { SHA1 } from 'crypto-es/lib/sha1' | ||
import { reactive } from 'vue' | ||
import router from "../router" | ||
const initialState = { | ||
org: '', | ||
org: localStorage.getItem('/account/name') || '', | ||
email: localStorage.getItem('/member/email') || '', | ||
password: '', | ||
privacyPolicies: false, | ||
|
@@ -30,30 +29,21 @@ const isPasswordVisible = ref(false) | |
const register = () => { | ||
if (state.org && state.email && state.password && state.privacyPolicies) { | ||
// Do register | ||
// axios.get("http://local.getusers.com) | ||
// .then(response => { | ||
// this.users = response.data; | ||
// }) | ||
// .catch(error => { | ||
// console.log(error) | ||
// }) | ||
const salt = WordArray.random(128/8).toString() | ||
localStorage.setItem('/member/password', PBKDF2(state.password, salt, { keySize: 512/32, iterations: 1000 }).toString()) | ||
const passwordHash = new SHA1(state.password) | ||
axios.get(`/register/${state.org}/${state.email}/${passwordHash}`) | ||
.then(console.log) | ||
.catch(console.log) | ||
localStorage.setItem('/account/name', state.org) | ||
localStorage.setItem('/member/email', state.email) | ||
localStorage.setItem('/member/password/salt', salt) | ||
router.push('/dashboard') | ||
localStorage.setItem('/session/token', 'temp') | ||
router.push('/login') | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
<div class="auth-wrapper d-flex align-center justify-center pa-4"> | ||
<VCard | ||
class="auth-card pa-4 pt-7" | ||
max-width="448" | ||
> | ||
<VCard class="auth-card pa-4 pt-7" max-width="448"> | ||
<VCardItem class="justify-center"> | ||
<template #prepend> | ||
<div class="d-flex"> | ||
|
@@ -76,73 +66,34 @@ const register = () => { | |
<VRow> | ||
<!-- Org --> | ||
<VCol cols="12"> | ||
<VTextField | ||
required | ||
v-model="state.org" | ||
autofocus | ||
label="Organization" | ||
placeholder="ACME Corp." | ||
/> | ||
<VTextField required v-model="state.org" autofocus label="Organization" placeholder="ACME Corp." /> | ||
</VCol> | ||
<!-- email --> | ||
<VCol cols="12"> | ||
<VTextField | ||
required | ||
v-model="state.email" | ||
label="Email" | ||
placeholder="[email protected]" | ||
type="email" | ||
/> | ||
<VTextField required v-model="state.email" label="Email" placeholder="[email protected]" type="email" /> | ||
</VCol> | ||
|
||
<!-- password --> | ||
<VCol cols="12"> | ||
<VTextField | ||
required | ||
v-model="state.password" | ||
label="Password" | ||
placeholder="············" | ||
<VTextField required v-model="state.password" label="Password" placeholder="············" | ||
:type="isPasswordVisible ? 'text' : 'password'" | ||
:append-inner-icon="isPasswordVisible ? 'bx-hide' : 'bx-show'" | ||
@click:append-inner="isPasswordVisible = !isPasswordVisible" | ||
/> | ||
@click:append-inner="isPasswordVisible = !isPasswordVisible" /> | ||
<div class="d-flex align-center mt-1 mb-4"> | ||
<VCheckbox | ||
required | ||
id="privacy-policy" | ||
v-model="state.privacyPolicies" | ||
inline | ||
/> | ||
<VLabel | ||
for="privacy-policy" | ||
style="opacity: 1;" | ||
> | ||
<VCheckbox required id="privacy-policy" v-model="state.privacyPolicies" inline /> | ||
<VLabel for="privacy-policy" style="opacity: 1;"> | ||
<span class="me-1">I agree to</span> | ||
<a | ||
href="javascript:void(0)" | ||
class="text-primary" | ||
>privacy policy & terms</a> | ||
<a href="javascript:void(0)" class="text-primary">privacy policy & terms</a> | ||
</VLabel> | ||
</div> | ||
|
||
<VBtn | ||
@click="v$.$validate" | ||
block | ||
text="Sign up" | ||
type="submit" | ||
/> | ||
<VBtn @click="v$.$validate" block text="Sign up" type="submit" /> | ||
</VCol> | ||
|
||
<!-- login instead --> | ||
<VCol | ||
cols="12" | ||
class="text-center text-base" | ||
> | ||
<VCol cols="12" class="text-center text-base"> | ||
<span>Already have an account?</span> | ||
<RouterLink | ||
class="text-primary ms-2" | ||
to="/login" | ||
> | ||
<RouterLink class="text-primary ms-2" to="/login"> | ||
Sign in instead | ||
</RouterLink> | ||
</VCol> | ||
|
@@ -155,6 +106,7 @@ const register = () => { | |
|
||
<style lang="scss" scoped> | ||
@use "@core/scss/template/pages/page-auth.scss"; | ||
.v-btn { | ||
text-transform: none; | ||
} | ||
|