The official web SDK for integrating Glide's carrier-grade phone verification into your web applications. Supports React, Vue, Angular, and vanilla JavaScript/TypeScript.
- 🚀 Instant Verification: Direct carrier verification without SMS
- 🔐 Fraud Resistant: Can't be intercepted or spoofed like SMS codes
- ⚡ Real-time Progress: Track verification steps with detailed state management
- 🌐 Framework Support: React, Vue 3, Angular, and vanilla JS/TS
- 🛡️ Type Safe: Full TypeScript support with comprehensive types
- 🎯 Developer Friendly: Clear error messages and browser compatibility checks
- Installation
- Quick Start
- Framework Examples
- Error Handling
- Browser Support
- API Reference
- Testing
- Contributing
npm install glide-web-client-sdk
or
yarn add glide-web-client-sdk
<template>
<div>
<button @click="getNumber" :disabled="isLoading">
{{ isLoading ? 'Verifying...' : 'Get My Phone Number' }}
</button>
<!-- Progress indicator -->
<div v-if="isLoading">
{{ currentStep }}:
<span v-if="currentStep === 'requesting'">Preparing request...</span>
<span v-if="currentStep === 'authenticating'">Waiting for carrier approval...</span>
<span v-if="currentStep === 'processing'">Processing response...</span>
</div>
<div v-if="error" class="error">
{{ error.message }}
</div>
<div v-if="result" class="success">
Phone: {{ result.phoneNumber }}
</div>
</div>
</template>
<script setup>
import { usePhoneAuth } from 'glide-web-client-sdk/vue'
const {
getPhoneNumber,
verifyPhoneNumber,
isLoading,
error,
result,
currentStep,
isSupported
} = usePhoneAuth({
endpoints: {
prepare: '/api/phone-auth/prepare',
process: '/api/phone-auth/process'
}
})
const getNumber = async () => {
try {
await getPhoneNumber()
} catch (err) {
console.error('Verification failed:', err)
}
}
</script>
import { usePhoneAuth } from 'glide-web-client-sdk/react'
function PhoneVerification() {
const {
getPhoneNumber,
verifyPhoneNumber,
isLoading,
error,
result,
currentStep,
isSupported
} = usePhoneAuth({
endpoints: {
prepare: '/api/phone-auth/prepare',
process: '/api/phone-auth/process'
}
})
const handleGetNumber = async () => {
try {
await getPhoneNumber()
} catch (err) {
console.error('Verification failed:', err)
}
}
const handleVerifyNumber = async (phoneNumber) => {
try {
await verifyPhoneNumber(phoneNumber)
} catch (err) {
console.error('Verification failed:', err)
}
}
if (!isSupported) {
return <div>Browser not supported. Please enable Digital Credentials API.</div>
}
return (
<div>
<button onClick={handleGetNumber} disabled={isLoading}>
{isLoading ? `${currentStep}...` : 'Get My Phone Number'}
</button>
{error && <div className="error">{error.message}</div>}
{result && <div className="success">Phone: {result.phoneNumber}</div>}
</div>
)
}
import { Component } from '@angular/core'
import { PhoneAuthService } from 'glide-web-client-sdk/angular'
@Component({
selector: 'app-phone-verification',
template: `
<button (click)="getNumber()" [disabled]="isLoading$ | async">
{{ (isLoading$ | async) ? (currentStep$ | async) : 'Get My Phone Number' }}
</button>
<div *ngIf="error$ | async as error" class="error">
{{ error.message }}
</div>
<div *ngIf="result$ | async as result" class="success">
Phone: {{ result.phoneNumber }}
</div>
`
})
export class PhoneVerificationComponent {
isLoading$ = this.phoneAuth.isLoading$
error$ = this.phoneAuth.error$
result$ = this.phoneAuth.result$
currentStep$ = this.phoneAuth.currentStep$
constructor(private phoneAuth: PhoneAuthService) {
// Configure the service
this.phoneAuth.configure({
endpoints: {
prepare: '/api/phone-auth/prepare',
process: '/api/phone-auth/process'
}
})
}
async getNumber() {
try {
await this.phoneAuth.getPhoneNumber()
} catch (err) {
console.error('Verification failed:', err)
}
}
}
import { PhoneAuthManager } from 'glide-web-client-sdk/vanilla'
// Initialize the manager
const phoneAuth = new PhoneAuthManager({
endpoints: {
prepare: '/api/phone-auth/prepare',
process: '/api/phone-auth/process'
}
})
// Subscribe to state changes
phoneAuth.subscribe((state) => {
console.log('Current state:', state)
if (state.isLoading) {
document.getElementById('status').textContent = state.currentStep
}
if (state.error) {
document.getElementById('error').textContent = state.error.message
}
if (state.result) {
document.getElementById('result').textContent = state.result.phoneNumber
}
})
// Verify phone
async function getPhoneNumber() {
try {
await phoneAuth.getPhoneNumber()
} catch (err) {
console.error('Verification failed:', err)
}
}
The SDK provides comprehensive error handling with typed errors and user-friendly messages.
interface AuthError {
code: string
message: string
details?: any
browserError?: {
name: string
message: string
stack?: string
code?: number
}
context?: {
step: 'prepare' | 'prompt' | 'process'
timestamp: string
userAgent?: string
url?: string
}
}
Code | Description | User Action |
---|---|---|
BROWSER_NOT_SUPPORTED |
Digital Credentials API not available | Enable Chrome flag |
USER_DENIED |
User cancelled authentication | Try again |
CARRIER_NOT_ELIGIBLE |
Carrier doesn't support verification | Use alternative method |
SESSION_NOT_FOUND |
Session expired | Retry verification |
RATE_LIMIT_EXCEEDED |
Too many attempts | Wait before retrying |
NETWORK_ERROR |
Network connection failed | Check connection |
import {
isPhoneAuthError,
isUserError,
getUserMessage,
PhoneAuthErrorCode
} from 'glide-web-client-sdk/vue' // or /react, /angular, /vanilla
try {
await verifyPhoneNumber('+1234567890')
} catch (error) {
if (isPhoneAuthError(error)) {
// Check for specific error types
if (error.code === PhoneAuthErrorCode.CARRIER_NOT_ELIGIBLE) {
console.log('Carrier not supported')
} else if (error.code === PhoneAuthErrorCode.USER_DENIED) {
console.log('User cancelled')
} else if (isUserError(error)) {
// Show user-friendly message
alert(getUserMessage(error))
}
// Log error details for debugging
console.error('Error details:', {
code: error.code,
step: error.context?.step,
browserError: error.browserError
})
}
}
The SDK requires the Digital Credentials API, which is currently available in:
- ✅ Chrome 117+ (with flag enabled)
- ✅ Edge 117+ (with flag enabled)
- ❌ Firefox (not supported)
- ❌ Safari (not supported)
- Open Chrome or Edge
- Navigate to:
- Chrome:
chrome://flags/#web-identity-digital-credentials
- Edge:
edge://flags/#web-identity-digital-credentials
- Chrome:
- Set the flag to "Enabled" (not "Default")
- Click "Relaunch" to restart the browser
import { usePhoneAuth } from 'glide-web-client-sdk/vue'
const { isSupported } = usePhoneAuth()
if (!isSupported) {
console.log('Browser not supported. Please enable Digital Credentials API.')
}
interface AuthConfig {
endpoints?: {
prepare?: string // Default: '/api/phone-auth/prepare'
process?: string // Default: '/api/phone-auth/process'
}
timeout?: number // Default: 30000 (30 seconds)
debug?: boolean // Default: false
}
Retrieves the user's phone number from their device.
const result = await getPhoneNumber({
consentData: {
consentText: 'I agree to the terms',
policyLink: 'https://example.com/privacy',
policyText: 'Privacy Policy'
}
})
Verifies ownership of a specific phone number.
const result = await verifyPhoneNumber('+1234567890', {
consentData: {
consentText: 'I agree to verify my phone',
policyLink: 'https://example.com/terms'
}
})
Property | Type | Description |
---|---|---|
isLoading |
boolean |
Whether verification is in progress |
error |
AuthError | null |
Current error if any |
result |
PhoneAuthResult | null |
Verification result |
currentStep |
'idle' | 'requesting' | 'authenticating' | 'processing' | 'complete' |
Current verification step |
isSupported |
boolean |
Whether browser supports the API |
For advanced use cases, you can access the low-level PhoneAuthClient methods:
import { PhoneAuthClient } from 'glide-web-client-sdk'
const client = new PhoneAuthClient({
endpoints: {
prepare: '/api/phone-auth/prepare',
process: '/api/phone-auth/process'
}
})
// Manual flow
const request = await client.preparePhoneRequest({
useCase: 'VerifyPhoneNumber',
phoneNumber: '+1234567890'
})
const credential = await client.invokeSecurePrompt(request)
const result = await client.processPhoneResponse(
credential,
request.session,
{ useCase: 'VerifyPhoneNumber' }
)
The SDK requires two backend endpoints. You can implement these using the Glide Node SDK or your own backend.
import { GlideClient } from '@glideidentity/sdk'
const glide = new GlideClient({
clientId: process.env.GLIDE_CLIENT_ID,
clientSecret: process.env.GLIDE_CLIENT_SECRET,
redirectUri: process.env.GLIDE_REDIRECT_URI,
})
// Prepare endpoint
app.post('/api/phone-auth/prepare', async (req, res) => {
try {
const request = await glide.magicAuth.phoneNumbers.generateRequest({
useCase: req.body.use_case,
phoneNumber: req.body.phone_number,
consentData: req.body.consent_data
})
res.json(request)
} catch (error) {
res.status(error.status || 500).json({ error: error.message })
}
})
// Process endpoint
app.post('/api/phone-auth/process', async (req, res) => {
try {
const result = await glide.magicAuth.phoneNumbers.authenticate({
session: req.body.session,
response: req.body.response
})
res.json(result)
} catch (error) {
res.status(error.status || 500).json({ error: error.message })
}
})
npm test
For testing in development, you can use the Glide demo server:
const { getPhoneNumber } = usePhoneAuth({
endpoints: {
prepare: 'https://checkout-demo-server.glideidentity.dev/generate-get-request',
process: 'https://checkout-demo-server.glideidentity.dev/processCredential'
}
})
We welcome contributions! Please see our Contributing Guide for details.
MIT © Glide Identity
- 📧 Email: support@glideidentity.com
- 💬 Discord: Join our community
- 📚 Docs: https://docs.glideidentity.com