Skip to content

Commit

Permalink
feat: registration D1
Browse files Browse the repository at this point in the history
Signed-off-by: 0x73746F66 <[email protected]>
  • Loading branch information
0x73746F66 committed Jun 11, 2024
1 parent fffee16 commit 8180769
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 70 deletions.
4 changes: 2 additions & 2 deletions functions/github/install/[installation_id]/[code].js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const onRequestGet = async context => {
if (context.params?.code) { //installation_id
if (context.params?.code) {
console.log('installation_id', context.params?.installation_id)
const method = "POST"
const url = new URL("https://github.com/login/oauth/access_token")
Expand All @@ -10,5 +10,5 @@ export const onRequestGet = async context => {
}).toString()
return fetch(url, { method })
}
return new Response({ 'err': 'OAuth authorization code not provided' })
return new Response.json({ 'err': 'OAuth authorization code not provided' })
}
36 changes: 36 additions & 0 deletions functions/login/[email]/[hash].js
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
}
32 changes: 32 additions & 0 deletions functions/register/[org]/[email]/[hash].js
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)
}
88 changes: 20 additions & 68 deletions src/pages/Register.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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">
Expand All @@ -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>
Expand All @@ -155,6 +106,7 @@ const register = () => {

<style lang="scss" scoped>
@use "@core/scss/template/pages/page-auth.scss";
.v-btn {
text-transform: none;
}
Expand Down

0 comments on commit 8180769

Please sign in to comment.