Authentication Providers
SOLID supports multiple authentication methods through its provider system, offering flexibility in how users can sign up and log in to your application.
Supported Providers
Section Management
- Traditional username/password
- Password policies
- Password reset flow
- Account recovery
Section Management
- Email-based OTP
- SMS-based OTP
- Time-based tokens
- Recovery codes
Section Management
- Meta/Facebook
- Twitter/X
- Custom OAuth providers
Authentication Flow
Standard OAuth Flow
1. Frontend initiates auth:
// Redirect to OAuth provider
window.location.href = "https://solid.website.com/api/iam/[provider]/connect";
2. Backend handles callback:
https://solid.website.com/api/iam/[provider]/connect/callback
3. Provider redirects with code:
http://website.com/connect/[provider]/callback?accessCode=[code]
4. Frontend exchanges code:
GET https://solid.website.com/api/iam/[provider]/auth?accessCode=[code]
5. Backend returns JWT:
{
"token": "eyJhbGciOiJIUzI1...",
"user": {
"id": "123",
"email": "user@example.com",
"profile": {}
}
}
Provider Configuration
Standard OAuth Flow
{
"provider": "password",
"config": {
"minLength": 8,
"requireNumbers": true,
"requireSpecialChars": true,
"requireUppercase": true,
"passwordHistory": 5,
"maxAttempts": 5,
"lockoutDuration": 300
}
}
OTP Provider
{
"provider": "otp",
"config": {
"type": "email",
"codeLength": 6,
"expiry": 300,
"rateLimit": {
"window": 3600,
"max": 5
}
}
}
OAuth Provider (Google Example)
{
"provider": "google",
"config": {
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"redirectUri": "https://solid.website.com/api/iam/google/connect/callback",
"scopes": ["email", "profile"]
}
}
Features
Multi-factor Authentication (MFA)
- Enable/disable per user
- Multiple MFA methods
- Backup codes
- Remember device option
Session Management
- JWT tokens
- Refresh tokens
- Token expiry
- Session invalidation
Account Recovery
- Email recovery
- Security questions
- Admin assistance
- Recovery codes
Security Features
Password Security
- Secure hashing (bcrypt)
- Password policies
- Brute force protection
- Password history
OAuth Security
- State parameter
- PKCE support
- Scope validation
- Token validation
General Security
- Rate limiting
- IP blocking
- Audit logging
- Session monitoring
Implementation Examples
Adding Google Authentication
- Configure Provider:
{
"name": "google",
"enabled": true,
"config": {
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"redirectUri": "https://solid.website.com/api/iam/google/connect/callback",
"scopes": ["email", "profile"],
"mapping": {
"email": "email",
"name": "displayName",
"picture": "photoUrl"
}
}
}
- Frontend Integration:
function initiateGoogleAuth() {
window.location.href = "https://solid.website.com/api/iam/google/connect";
}
async function handleCallback(accessCode) {
const response = await fetch(
`https://solid.website.com/api/iam/google/auth?accessCode=${accessCode}`
);
const { token, user } = await response.json();
// Store token and handle user session
}
Implementing OTP Authentication
- Configure Provider:
{
"name": "email_otp",
"enabled": true,
"config": {
"type": "email",
"template": "auth_otp",
"codeLength": 6,
"expiry": 300,
"rateLimit": {
"window": 3600,
"max": 5
}
}
}
- Authentication Flow:
// Request OTP
async function requestOTP(email) {
await fetch("/api/iam/otp/request", {
method: "POST",
body: JSON.stringify({ email }),
});
}
// Verify OTP
async function verifyOTP(email, code) {
const response = await fetch("/api/iam/otp/verify", {
method: "POST",
body: JSON.stringify({ email, code }),
});
const { token, user } = await response.json();
// Handle successful authentication
}
@Auth(AuthType.None)
@Controller("iam/google")
@ApiTags("Iam")
export class GoogleAuthenticationController {
constructor(
@Inject(iamConfig.KEY)
private iamConfiguration: ConfigType<typeof iamConfig>,
private readonly userService: UserService,
private readonly authService: AuthenticationService
) {}
@Public()
@UseGuards(GoogleOauthGuard)
@Get("connect")
async connect() {
this.validateConfiguration();
}
private validateConfiguration() {
if (!isGoogleOAuthConfigured(this.iamConfiguration)) {
throw new InternalServerErrorException("Google OAuth is not configured");
}
}
@Public()
@Get("connect/callback")
@UseGuards(GoogleOauthGuard)
googleAuthCallback(@Req() req: Request, @Res() res: Response) {
this.validateConfiguration();
const user = req.user;
// console.log(`Found user: ${JSON.stringify(user)}`);
// const token = await this.authService.signIn(req.user);
// res.cookie('access_token', token, {
// maxAge: 2592000000,
// sameSite: true,
// secure: false,
// });
// return req.user;
// return res;
return res.redirect(
`${this.iamConfiguration.googleOauth.redirectURL}?accessCode=${user["accessCode"]}`
);
}
/**
* This is just a dummy endpoint where we are passing in the accessCode, this will be configured in the .env as an environment variable and
* will be passed the accessCode, using the accessCode the UI code on this page will mostly invoke the /iam/google/auth endpoint which will finally generate the JWT token.
*
* @param accessCode
* @returns
*/
@Public()
@Get("dummy-redirect")
async dummyGoogleAuthRedirect(@Query("accessCode") accessCode) {
this.validateConfiguration();
const user = await this.userService.findOneByAccessCode(accessCode);
delete user["password"];
return user;
}
/**
* Use this endpoint to authenticate using an accessCode with Google.
*
* @param accessCode
* @returns
*/
@Public()
@Get("authenticate")
@ApiQuery({ name: "accessCode", required: true, type: String })
async googleAuth(@Query("accessCode") accessCode) {
this.validateConfiguration();
return this.authService.signInUsingGoogle(accessCode);
}
}
Best Practices
Provider Selection
- Consider user base
- Evaluate security needs
- Plan backup methods
- Test all flows
Configuration
- Secure credentials
- Set proper timeouts
- Configure rate limits
- Enable logging
User Experience
- Clear error messages
- Simple recovery flows
- Multiple auth options
- Remember user preferences
Security
- Regular audits
- Monitor failed attempts
- Review permissions
- Update configurations