Skip to content

Commit

Permalink
Merge pull request #94 from hanzoai/auth/custom-token-auth
Browse files Browse the repository at this point in the history
Auth: added support for common auth
  • Loading branch information
zeekay authored Apr 18, 2024
2 parents 2014fe4 + e1cbd02 commit 986d37b
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/auth/components/auth-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const AuthWidget: React.FC<{
</Button>
) : (
<LinkElement
def={{href: '/login', title: 'Login', variant: 'primary'} satisfies LinkDef}
def={{href: `${process.env.NEXT_PUBLIC_AUTH_ORIGIN}/login`, title: 'Login', variant: 'primary'} satisfies LinkDef}
className='h-8 w-fit !min-w-0'
/>
)
Expand Down
16 changes: 11 additions & 5 deletions packages/auth/components/login-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const LoginPanel: React.FC<PropsWithChildren & {
className?: string,
inputClx?: string,
noHeading?: boolean
onLoginChanged?: (loggedIn: boolean) => void
onLoginChanged?: (token: string) => void
termsOfServiceUrl?: string
privacyPolicyUrl?: string
}> = observer(({
Expand All @@ -61,11 +61,17 @@ const LoginPanel: React.FC<PropsWithChildren & {

const [isLoading, setIsLoading] = useState(false)

const succeed = (loggedOut = false) => {
// If a callback is provide, don't redirect.
// Assume host code is handling (eg, mobile menu)
const succeed = async () => {
// If a callback is provide, don't redirect.
// Assume host code is handling (eg, mobile menu)
if (onLoginChanged) {
onLoginChanged(!loggedOut)
const res = await fetch(
'/api/auth/generate-custom-token',
{ method: 'POST' }
).then(res => res.json())
if (res.success) {
onLoginChanged(res.token.token)
}
}
else if (redirectUrl) {
router.push(redirectUrl)
Expand Down
19 changes: 19 additions & 0 deletions packages/auth/server/firebase-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ async function getSession() {
}
}

export const generateCustomToken = async (): Promise<{success: boolean, token: string | null}> => {
const session = await getSession()

if (!(await isUserAuthenticated(session))) {
return {success: false, token: null}
}

const decodedIdToken = await auth.verifySessionCookie(session!)
const currentUser = await auth.getUser(decodedIdToken.uid)

try {
const token = await auth.createCustomToken(currentUser.uid)
return {success: true, token}
} catch (e) {
console.error('Error generating custom token', e)
return {success: false, token: null}
}
}

export async function createSessionCookie(idToken: string, sessionCookieOptions: SessionCookieOptions) {
return auth.createSessionCookie(idToken, sessionCookieOptions)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { getUserServerSide } from './firebase-support'
export { getUserServerSide, generateCustomToken } from './firebase-support'
export {
handleLogin as handleLoginApiRequest,
handleLogout as handleLogoutApiRequest
Expand Down
4 changes: 4 additions & 0 deletions packages/auth/service/auth-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ interface AuthService {
provider: 'google' | 'facebook' | 'github'
) => Promise<{success: boolean, userInfo: HanzoUserInfo | null}>

loginWithCustomToken: (
token: string
) => Promise<{success: boolean, userInfo: HanzoUserInfo | null}>

associateWallet: () => Promise<void>

logout: () => Promise<{success: boolean}>
Expand Down
32 changes: 32 additions & 0 deletions packages/auth/service/impl/firebase-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
createUserWithEmailAndPassword,
type User,
signInWithEmailAndPassword,
signInWithCustomToken,
} from 'firebase/auth'

import { initializeApp, getApps } from "firebase/app"
Expand Down Expand Up @@ -140,6 +141,37 @@ export async function loginWithEmailAndPassword(
}
}

export async function loginWithCustomToken(
token: string,
): Promise<{success: boolean, user?: User }> {

let user: User | undefined = undefined
const userCredential = await signInWithCustomToken(auth, token)
user = userCredential.user

try {
const idToken = await user.getIdToken()

const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ idToken }),
})
const resBody = (await response.json()) as unknown as APIResponse<string>

if (response.ok && resBody.success) {
return { success: true, user }
}
else {
return {success: false}
}
}
catch (error) {
console.error('Error signing in with Firebase auth', error)
return {success: false}
}
}

export async function logoutBackend(): Promise<{success: boolean}> {

try {
Expand Down
32 changes: 32 additions & 0 deletions packages/auth/service/impl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { AuthServiceConf, HanzoUserInfo, HanzoUserInfoValue } from '../../t

import {
auth as fbAuth,
loginWithCustomToken,
loginWithEmailAndPassword,
loginWithProvider,
logoutBackend
Expand Down Expand Up @@ -133,6 +134,37 @@ class AuthServiceImpl implements AuthService {
}
}

loginWithCustomToken = async (
token: string
): Promise<{success: boolean, userInfo: HanzoUserInfo | null}> => {

try {
this._hzUser.clear()
const res = await loginWithCustomToken(token)
if (res.success && res.user) {
const walletAddress = res.user.email ? await getAssociatedWalletAddress(res.user.email) : undefined
this._hzUser.set({
email: res.user.email ?? '',
displayName : res.user.displayName ?? null,
walletAddress : walletAddress?.result ?? null
})

return {
success: true,
userInfo: this._hzUser
}
}
return {
success: false,
userInfo: null
}
}
catch (e) {
console.error('Error signing in with Firebase auth', e)
return {success: false, userInfo: null}
}
}

associateWallet = async (): Promise<void> => {
if (this._hzUser.isValid) {
const res = await associateWalletAddressWithAccount(this._hzUser.email)
Expand Down

0 comments on commit 986d37b

Please sign in to comment.