@goiam/react
Installation
Bash
npm install @goiam/react
Bash
yarn add @goiam/react
Features
- 🔐 Easy Authentication: Simple integration with Go-IAM server
- � High Performance: Built with Hookstate for minimal re-renders
- 🎯 Resource-Based Access Control: Support for resource-based authorization
- 🪝 Simple Hook API: Easy access to authentication state and methods
- 💾 Persistent Storage: Automatic user data storage and retrieval
- 🔄 Auto Refresh: Automatic user profile updates with smart caching
- 📱 TypeScript Support: Full TypeScript support with comprehensive types
- ⚡ PKCE Support: Secure OAuth2 PKCE flow implementation
Quick Start
1. Basic Setup
Tsx
import React from 'react';
import { useGoIam } from '@goiam/react';
function LoginButton() {
const { user, login, logout, loadedState } = useGoIam();
if (!loadedState) {
return <div>Loading...</div>;
}
if (user) {
return (
<div>
<p>Welcome, {user.name || user.email}!</p>
<button onClick={logout}>Logout</button>
</div>
);
}
return <button onClick={login}>Login</button>;
}
2. Configure Your App
Tsx
import React, { useEffect } from 'react';
import { useGoIam } from '@goiam/react';
function App() {
const { setBaseUrl, setClientId, dashboardMe } = useGoIam();
useEffect(() => {
// Configure the SDK
setBaseUrl('https://your-goiam-server.com');
setClientId('your-client-id');
// Load user data on app start
dashboardMe();
}, [setBaseUrl, setClientId, dashboardMe]);
return <div>Your App Content</div>;
}
3. Handle Authentication Callback
Tsx
import React, { useEffect } from 'react';
import { useGoIam } from '@goiam/react';
function CallbackScreen() {
const { user, verify, loadedState, verifying } = useGoIam();
useEffect(() => {
// Extract parameters from URL query string
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const codeChallenge = localStorage.getItem('code_challenge'); // Stored during login
if (code && codeChallenge && !user && !verifying) {
// Complete authentication
verify(codeChallenge, code);
}
}, [verify, user, verifying]);
if (verifying) {
return <div>Completing authentication...</div>;
}
if (!loadedState) {
return <div>Loading...</div>;
}
if (user) {
return (
<div>
<p>Welcome back, {user.name || user.email}!</p>
<a href="/">Go to Dashboard</a>
</div>
);
}
return <div>Authentication failed. Please try again.</div>;
}
4. Resource-Based Access Control
Tsx
import React from 'react';
import { useGoIam } from '@goiam/react';
function AdminPanel() {
const { user, hasRequiredResources } = useGoIam();
if (!user) {
return <div>Please log in to access this area.</div>;
}
if (!hasRequiredResources(['admin', 'user_management'])) {
return <div>You don't have permission to access this area.</div>;
}
return (
<div>
<h2>Admin Panel</h2>
<p>Welcome to the admin area!</p>
</div>
);
}
5. Using AuthGuard for Route Protection
Tsx
import React from 'react';
import { AuthGuard } from '@goiam/react';
// Basic route protection
function ProtectedRoute() {
return (
<AuthGuard>
<div>This content is only visible to authenticated users!</div>
</AuthGuard>
);
}
// Auto-redirect to login
function AutoRedirectRoute() {
return (
<AuthGuard redirectToLogin={true}>
<div>Protected content with auto redirect</div>
</AuthGuard>
);
}
// Resource-based protection
function AdminRoute() {
return (
<AuthGuard requiredResources={['admin']}>
<div>Admin-only content</div>
</AuthGuard>
);
}
// Custom fallback components
function CustomFallbackRoute() {
const CustomLogin = () => (
<div style={{ textAlign: 'center', padding: '2rem' }}>
<h3>🔒 Login Required</h3>
<p>Please sign in to continue</p>
</div>
);
const CustomUnauthorized = () => (
<div style={{ textAlign: 'center', padding: '2rem' }}>
<h3>⛔ Access Denied</h3>
<p>You need admin permissions</p>
</div>
);
return (
<AuthGuard
requiredResources={['admin']}
fallback={CustomLogin}
unauthorizedComponent={CustomUnauthorized}
>
<div>Protected admin content</div>
</AuthGuard>
);
}
Using the withAuthGuard HOC
Tsx
import React from 'react';
import { withAuthGuard } from '@goiam/react';
// Basic component protection
const ProtectedComponent = () => <div>This component is protected!</div>;
export const GuardedComponent = withAuthGuard(ProtectedComponent);
// With guard options
const AdminComponent = () => <div>Admin dashboard content</div>;
export const GuardedAdminComponent = withAuthGuard(AdminComponent, {
requiredResources: ['admin'],
redirectToLogin: true,
});
// Usage in your app
function App() {
return (
<div>
<GuardedComponent />
<GuardedAdminComponent />
</div>
);
}
AuthGuard Props
Prop | Type | Default | Description |
---|---|---|---|
`children` | `ReactNode` | - | Content to render when authenticated and authorized |
`fallback` | `ComponentType` | `DefaultUnauthenticatedComponent` | Component to show when user is not authenticated |
`redirectToLogin` | `boolean` | `false` | Automatically redirect to login page if not authenticated |
`requiredResources` | `string[]` | `[]` | Array of required resource permissions |
`unauthorizedComponent` | `ComponentType` | `DefaultUnauthorizedComponent` | Component to show when user lacks required resources |
API Reference
useGoIam Hook
Tsx
const {
// State
user, // User | undefined: Current user data
loadedState, // boolean: Whether initial data load is complete
clientAvailable, // boolean: Whether client is properly configured
verifying, // boolean: Whether verification is in progress
loadingMe, // boolean: Whether user data is being fetched
verified, // boolean: Whether user has verified their account
err, // string: Any error message
baseUrl, // string: Current base URL
clientId, // string: Current client ID
loginPageUrl, // string: Login page URL
callbackPageUrl, // string: Callback page URL
// Actions
login, // () => void: Redirect to login
logout, // () => void: Clear user data and logout
verify, // (codeChallenge: string, code: string) => Promise<void>: Complete authentication
dashboardMe, // (dontUpdateTime?: boolean) => Promise<void>: Fetch user dashboard data
me, // () => Promise<void>: Fetch user profile
hasRequiredResources, // (resources: string[]) => boolean: Check user permissions
// Configuration
setBaseUrl, // (url: string) => void: Set API base URL
setClientId, // (id: string) => void: Set client ID
setLoginPageUrl, // (url: string) => void: Set login page URL
setCallbackPageUrl, // (url: string) => void: Set callback page URL
setLoadingMe, // (loading: boolean) => void: Set loading state
} = useGoIam();
Key Methods
dashboardMe(dontUpdateTime?: boolean)
Tsx
// Standard fetch with caching
await dashboardMe();
// Force fetch, bypass cache
await dashboardMe(true);
verify(codeChallenge: string, code: string)
Tsx
const codeChallenge = localStorage.getItem('code_challenge');
const code = new URLSearchParams(window.location.search).get('code');
await verify(codeChallenge, code);
hasRequiredResources(resources: string[])
Tsx
// Check single resource
const canAdmin = hasRequiredResources(['admin']);
// Check multiple resources (user must have ALL)
const canManageUsers = hasRequiredResources(['admin', 'user_management']);
User Data Structure
Tsx
interface User {
id: string;
name: string;
email: string;
profile_pic: string;
created_at: string;
updated_at: string;
created_by: string;
updated_by: string;
enabled: boolean;
expiry: string;
resources: Record<string, Resource>; // Resource permissions
roles: Record<string, Role>; // User roles
}
interface Resource {
id: string;
key: string;
name: string;
}
interface Role {
id: string;
name: string;
}
Authentication Flow
- Initialization: Hook checks for stored user data and validates with API
- Configuration: Set base URL and client ID using setBaseUrl() and setClientId()
- Login: User clicks login → generates PKCE challenge → redirects to GoIAM auth URL
- Callback: After successful authentication, user returns to your app with authorization code
- Verification: Call verify() with code challenge and authorization code
- Profile Fetch: SDK automatically fetches and stores user profile data
- State Management: Authentication state is maintained globally with Hookstate