Authentication Providers
NexAuth’s provider system allows you to create custom authentication providers for specialized authentication needs.Provider Interface
Basic Provider
public interface AuthProvider {
/**
* Authenticate a player with given credentials
*/
AuthResult authenticate(String username, String password);
/**
* Register a new account
*/
AuthResult register(String username, String password);
/**
* Check if username is premium
*/
boolean isPremium(String username);
/**
* Get UUID for username
*/
UUID getUUID(String username);
/**
* Get provider name
*/
String getName();
}
Built-in Providers
PremiumAuthProvider
Handles Minecraft premium authentication:PremiumAuthProvider provider = new PremiumAuthProvider(sessionServer);
// Authenticate premium player
AuthResult result = provider.authenticate(username, null);
if (result.isSuccess()) {
UUID premiumUUID = result.getUUID();
// Handle premium authentication
}
OfflineAuthProvider
Handles offline/cracked authentication:OfflineAuthProvider provider = new OfflineAuthProvider(database);
// Authenticate with password
AuthResult result = provider.authenticate(username, password);
if (result.isSuccess()) {
// Handle offline authentication
}
FloodgateAuthProvider
Handles Bedrock player authentication:FloodgateAuthProvider provider = new FloodgateAuthProvider(floodgate);
// Authenticate Bedrock player
AuthResult result = provider.authenticate(username, floodgateUUID);
if (result.isSuccess()) {
// Handle Bedrock authentication
}
Custom Providers
Creating Custom Provider
public class CustomAuthProvider implements AuthProvider {
private final CustomAuthService service;
public CustomAuthProvider(CustomAuthService service) {
this.service = service;
}
@Override
public AuthResult authenticate(String username, String password) {
try {
// Call custom authentication service
boolean valid = service.authenticate(username, password);
if (valid) {
return AuthResult.success()
.withUUID(service.getUUID(username))
.withPremium(service.isPremium(username));
} else {
return AuthResult.failure("Invalid credentials");
}
} catch (Exception e) {
return AuthResult.failure("Authentication error: " + e.getMessage());
}
}
@Override
public AuthResult register(String username, String password) {
if (service.userExists(username)) {
return AuthResult.failure("User already exists");
}
boolean created = service.createUser(username, password);
return created ?
AuthResult.success() :
AuthResult.failure("Failed to create user");
}
@Override
public boolean isPremium(String username) {
return service.isPremium(username);
}
@Override
public UUID getUUID(String username) {
return service.getUUID(username);
}
@Override
public String getName() {
return "custom";
}
}
Registering Custom Provider
// Create provider instance
CustomAuthProvider provider = new CustomAuthProvider(customService);
// Register with NexAuth
NexAuthAPI api = NexAuthAPI.getInstance();
api.registerProvider("custom", provider);
// Set as default provider (optional)
api.setDefaultProvider("custom");
Provider Configuration
Provider Priority
NexAuth automatically handles provider priority:- Premium accounts (Mojang authentication)
- Offline accounts (password authentication)
- Floodgate accounts (Bedrock players)
Dynamic Provider Loading
// Load provider from configuration
String providerClass = config.getString("providers.custom.class");
AuthProvider provider = (AuthProvider) Class
.forName(providerClass)
.getDeclaredConstructor()
.newInstance();
// Configure provider
if (provider instanceof Configurable) {
((Configurable) provider).configure(config.getSection("providers.custom.settings"));
}
// Register provider
api.registerProvider("custom", provider);
Advanced Features
Provider Chaining
// Chain multiple providers
ChainedAuthProvider chainedProvider = new ChainedAuthProvider();
chainedProvider.addProvider(new PremiumAuthProvider());
chainedProvider.addProvider(new OfflineAuthProvider());
chainedProvider.addProvider(new CustomAuthProvider());
// Try each provider in order
AuthResult result = chainedProvider.authenticate(username, password);
if (result.isSuccess()) {
String providerName = result.getProviderName();
// Handle successful authentication
}
Provider Decorators
// Add caching to provider
CachingAuthProvider cachedProvider = new CachingAuthProvider(
new CustomAuthService(),
Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(1000)
.build()
);
// Add logging
LoggingAuthProvider loggingProvider = new LoggingAuthProvider(
cachedProvider,
logger
);
// Add rate limiting
RateLimitedAuthProvider rateLimitedProvider = new RateLimitedAuthProvider(
loggingProvider,
RateLimiter.create(10, TimeUnit.MINUTES)
);
Error Handling
Provider Errors
try {
AuthResult result = provider.authenticate(username, password);
if (result.isSuccess()) {
// Success
} else {
// Handle specific errors
switch (result.getErrorType()) {
case INVALID_CREDENTIALS:
// Handle invalid credentials
break;
case ACCOUNT_LOCKED:
// Handle locked account
break;
case PROVIDER_ERROR:
// Handle provider error
break;
}
}
} catch (ProviderException e) {
// Handle provider-specific exceptions
logger.error("Provider error: " + e.getMessage());
}
Testing
Mock Provider for Testing
public class MockAuthProvider implements AuthProvider {
private final Map<String, String> users = new HashMap<>();
public MockAuthProvider() {
// Add test users
users.put("testuser", "password");
}
@Override
public AuthResult authenticate(String username, String password) {
String storedPassword = users.get(username);
if (storedPassword != null && storedPassword.equals(password)) {
return AuthResult.success();
}
return AuthResult.failure("Invalid credentials");
}
// Implement other methods...
}
// Use in tests
MockAuthProvider mockProvider = new MockAuthProvider();
api.registerProvider("mock", mockProvider);
api.setDefaultProvider("mock");
Best Practices
Next Steps
Database API
Database integration and abstraction layer.

