GridLab Keycloak .NET Client - Skills Guide¶
Skill Type: Identity & Access Management
Technology Stack: .NET, Keycloak, OAuth 2.0, OpenID Connect
Complexity Level: Intermediate
Last Updated: 2024
📋 Overview¶
The Keycloak .NET client provides a high-level C# interface for communicating with Keycloak identity and access management servers, enabling seamless integration of authentication and authorization in your applications.
Key Capabilities¶
- ✅ Full Keycloak Admin REST API support
- ✅ Realm and client management
- ✅ User and group administration
- ✅ Role-based access control (RBAC)
- ✅ OpenID Connect integration
- ✅ Multi-realm support
Prerequisites¶
- .NET 9.0 or higher
- Keycloak server (version 12.0 or higher recommended)
- Admin credentials for Keycloak
- NuGet package manager
🚀 Quick Start¶
Step 1: Install NuGet Package¶
Install the Keycloak.Net package from NuGet:
dotnet add package Keycloak.Net
Package Information:
- Package Name: Keycloak.Net
- Repository: GitLab - Keycloak.Net
- NuGet: Keycloak.Net
Step 2: Configure Settings¶
Add Keycloak configuration to your appsettings.json:
{
"Keycloak": {
"Url": "https://your-keycloak-server/auth",
"RealmName": "your-realm-name",
"AdminUsername": "your-admin-username",
"AdminPassword": "your-admin-password"
}
}
Step 3: Create Configuration Class¶
Optionally, create a configuration class to hold settings:
public class KeycloakClientOptions
{
public string Url { get; set; } = string.Empty;
public string RealmName { get; set; } = string.Empty;
public string AdminUserName { get; set; } = string.Empty;
public string AdminPassword { get; set; } = string.Empty;
}
Step 4: Register Configuration¶
Configure options in your ABP module:
[DependsOn(
//...other dependencies
typeof(AbpAutofacModule) // Required for proper DI
)]
public class YourModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<KeycloakClientOptions>(options =>
{
options.Url = configuration["Keycloak:Url"]!;
options.AdminUserName = configuration["Keycloak:AdminUsername"]!;
options.AdminPassword = configuration["Keycloak:AdminPassword"]!;
options.RealmName = configuration["Keycloak:RealmName"]!;
});
}
}
💡 Usage Examples¶
Client Management¶
public class KeycloakClientSeeder : ITransientDependency
{
private readonly KeycloakClient _keycloakClient;
private readonly KeycloakClientOptions _keycloakOptions;
private readonly ILogger<KeycloakClientSeeder> _logger;
public KeycloakClientSeeder(
IOptions<KeycloakClientOptions> keycloakClientOptions,
ILogger<KeycloakClientSeeder> logger)
{
_keycloakOptions = keycloakClientOptions.Value;
_logger = logger;
_keycloakClient = new KeycloakClient(
_keycloakOptions.Url,
_keycloakOptions.AdminUserName,
_keycloakOptions.AdminPassword
);
}
public async Task CreateWebClientAsync()
{
var webClientId = "GMSS_Web";
var webClient = (await _keycloakClient.GetClientsAsync(
_keycloakOptions.RealmName,
clientId: webClientId
)).FirstOrDefault();
if (webClient == null)
{
var webRootUrl = "https://localhost:44322";
webClient = new Client
{
ClientId = webClientId,
Name = "Web Client",
Protocol = "openid-connect",
Enabled = true,
BaseUrl = webRootUrl,
RedirectUris = new List<string>
{
$"{webRootUrl}/signin-oidc"
},
ImplicitFlowEnabled = true, // for hybrid flow
FrontChannelLogout = true,
PublicClient = false,
Secret = "1q2w3e*"
};
webClient.Attributes = new Dictionary<string, object>
{
{ "post.logout.redirect.uris", $"{webRootUrl}/signout-callback-oidc" }
};
await _keycloakClient.CreateClientAsync(_keycloakOptions.RealmName, webClient);
_logger.LogInformation("Web client {ClientId} created successfully", webClientId);
}
else
{
_logger.LogInformation("Web client {ClientId} already exists", webClientId);
}
}
}
User Management¶
public class KeycloakUserService : ITransientDependency
{
private readonly KeycloakClient _keycloakClient;
private readonly string _realmName;
public KeycloakUserService(IOptions<KeycloakClientOptions> options)
{
var opts = options.Value;
_keycloakClient = new KeycloakClient(opts.Url, opts.AdminUserName, opts.AdminPassword);
_realmName = opts.RealmName;
}
public async Task<User> CreateUserAsync(string username, string email, string firstName, string lastName)
{
var user = new User
{
UserName = username,
Email = email,
FirstName = firstName,
LastName = lastName,
Enabled = true,
EmailVerified = true
};
await _keycloakClient.CreateUserAsync(_realmName, user);
return user;
}
public async Task AssignRoleToUserAsync(string userId, string roleName)
{
var role = await _keycloakClient.GetRoleByNameAsync(_realmName, roleName);
if (role != null)
{
await _keycloakClient.AddRealmRoleMappingsToUserAsync(
_realmName,
userId,
new[] { role }
);
}
}
}
Realm Management¶
public class KeycloakRealmService : ITransientDependency
{
private readonly KeycloakClient _keycloakClient;
public KeycloakRealmService(IOptions<KeycloakClientOptions> options)
{
var opts = options.Value;
_keycloakClient = new KeycloakClient(opts.Url, opts.AdminUserName, opts.AdminPassword);
}
public async Task<Realm> CreateRealmAsync(string realmName, string displayName)
{
var realm = new Realm
{
RealmName = realmName,
DisplayName = displayName,
Enabled = true,
SslRequired = "external",
RegistrationAllowed = true,
LoginWithEmailAllowed = true,
DuplicateEmailsAllowed = false,
ResetPasswordAllowed = true,
EditUsernameAllowed = false,
BruteForceProtected = true
};
await _keycloakClient.CreateRealmAsync(realm);
return realm;
}
}
📚 Best Practices¶
✅ Do's¶
- Store admin credentials securely (use Azure Key Vault, AWS Secrets Manager, etc.)
- Use service accounts for automated operations
- Implement proper error handling
- Use HTTPS for all Keycloak communications
- Validate realm and client existence before operations
- Log all administrative actions
❌ Don'ts¶
- Don't hardcode credentials in source code
- Don't use admin account for regular operations
- Don't expose Keycloak admin endpoints publicly
- Don't skip SSL certificate validation in production
- Don't store tokens in insecure locations
🔍 Troubleshooting¶
Common Issues¶
Issue: Authentication failed
- Solution: Verify admin username and password
- Solution: Check if admin user has required permissions
- Solution: Ensure realm name is correct
Issue: Connection timeout
- Solution: Verify Keycloak server URL
- Solution: Check network connectivity
- Solution: Verify firewall settings
Issue: Client already exists error
- Solution: Check for existing clients before creation
- Solution: Use update operation instead of create
📖 Additional Resources¶
- Keycloak Official Documentation
- Keycloak Admin REST API
- OpenID Connect Specification
- GitLab Repository
This documentation should help you set up and use the Keycloak client in your C# project.