@veas/protocol
Version:
Universal protocol for knowledge management and project tracking systems - enabling seamless interoperability between platforms and AI assistants
128 lines (103 loc) • 3.44 kB
text/typescript
/**
* Veas provider authentication implementation
*/
import type { AuthContext } from '../../protocols/common/index.js'
interface TokenCredentials {
token: string
}
interface ApiKeyCredentials {
apiKey: string
}
interface UsernamePasswordCredentials {
username: string
password: string
}
export type AuthCredentials = TokenCredentials | ApiKeyCredentials | UsernamePasswordCredentials
export class VeasAuthProvider {
private authContext: AuthContext | null = null
constructor(private config: { apiUrl: string }) {}
async authenticate(credentials: AuthCredentials): Promise<AuthContext> {
// Check cached auth context first
if (this.authContext) {
return this.authContext
}
let apiUrl = this.config.apiUrl
if (apiUrl.endsWith('/')) {
apiUrl = apiUrl.slice(0, -1)
}
// Handle token credentials
if ('token' in credentials) {
const response = await fetch(`${apiUrl}/auth/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${credentials.token}`,
},
})
if (!response.ok) {
throw new Error(`Authentication failed: ${response.status} ${response.statusText}`)
}
const data = await response.json() as any
this.authContext = {
userId: data.user?.id || data.userId,
organizationId: data.user?.organizationId || data.organizationId,
scopes: data.scopes || [],
expiresAt: data.expiresAt ? new Date(data.expiresAt) : undefined,
}
return this.authContext
}
// Handle API key credentials
if ('apiKey' in credentials) {
const response = await fetch(`${apiUrl}/auth/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': credentials.apiKey,
},
})
if (!response.ok) {
throw new Error(`Authentication failed: ${response.status} ${response.statusText}`)
}
const data = await response.json() as any
this.authContext = {
userId: data.user?.id || data.userId,
organizationId: data.user?.organizationId || data.organizationId,
scopes: data.scopes || [],
}
return this.authContext
}
// Handle username/password credentials
if ('username' in credentials && 'password' in credentials) {
const response = await fetch(`${apiUrl}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: credentials.username,
password: credentials.password,
}),
})
if (!response.ok) {
throw new Error(`Authentication failed: ${response.status} ${response.statusText}`)
}
const data = await response.json() as any
this.authContext = {
userId: data.user?.id || data.userId,
organizationId: data.user?.organizationId || data.organizationId,
scopes: data.scopes || [],
}
return this.authContext
}
throw new Error('Unsupported authentication method')
}
getAuthContext(): AuthContext | null {
return this.authContext
}
isAuthenticated(): boolean {
return this.authContext !== null
}
disconnect(): void {
this.authContext = null
}
}