.NET Core 基于Keycloak的用户名密码编程式认证示例求助
Hey there! Since you're new to .NET Core and need to implement programmatic authentication with Keycloak's OpenID Connect using the password grant flow (as you already mapped out with curl), let's walk through exactly how to build this step by step.
Prerequisites
- A recent .NET Core SDK installed
- A Keycloak realm set up with your
demo-appclient configured to allow the password grant type (make sure "Direct Access Grants Enabled" is toggled on for the client in Keycloak's admin console)
Step 1: Fetch Access Token from Keycloak
First, let's create a simple model to deserialize Keycloak's token response:
using System.Text.Json.Serialization; public class TokenResponse { [JsonPropertyName("access_token")] public string AccessToken { get; set; } [JsonPropertyName("token_type")] public string TokenType { get; set; } [JsonPropertyName("expires_in")] public int ExpiresIn { get; set; } }
Next, use HttpClient to send a request to Keycloak's token endpoint. While your curl example uses a GET request with query params, the OIDC specification recommends using POST with form data (more secure and widely supported):
using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; public async Task<TokenResponse> GetKeycloakTokenAsync() { var tokenEndpoint = "http://keycloakserver/auth/realms/realmName/protocol/openid-connect/token"; using var httpClient = new HttpClient(); var formData = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "password"), new KeyValuePair<string, string>("client_id", "demo-app"), new KeyValuePair<string, string>("username", "your-actual-username"), new KeyValuePair<string, string>("password", "your-actual-password") }); var response = await httpClient.PostAsync(tokenEndpoint, formData); response.EnsureSuccessStatusCode(); // Throws an exception if credentials are invalid or the request fails var responseJson = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<TokenResponse>(responseJson); }
Quick note: If you really need to match your original curl GET request, you can build a URL with the query params and send a
GetAsyncinstead — but POST with form data is the recommended approach.
Step 2: Call the Protected Service with the Access Token
Once you have the token, add it to the Authorization header of your request to the protected service:
public async Task CallProtectedServiceAsync(TokenResponse token) { var protectedServiceUrl = "https://your-protected-service/api/your-endpoint"; using var httpClient = new HttpClient(); // Add the Bearer token to the request header httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(token.TokenType, token.AccessToken); var response = await httpClient.GetAsync(protectedServiceUrl); response.EnsureSuccessStatusCode(); var serviceResponse = await response.Content.ReadAsStringAsync(); // Process the response from the protected service here (parse JSON, log, etc.) }
Putting It All Together
In your main application code (e.g., a console app, service class, or API controller), you can chain these methods like this:
public static async Task Main(string[] args) { var token = await GetKeycloakTokenAsync(); await CallProtectedServiceAsync(token); }
Key Best Practices to Follow
- Never hardcode credentials: Store usernames, passwords, and Keycloak endpoints in
appsettings.jsonor environment variables, and use .NET'sIConfigurationto read them. - Cache tokens: The
expires_invalue tells you how long the token is valid (in seconds). Cache it instead of fetching a new token for every request. - Use
IHttpClientFactory: In production apps, avoid creating a newHttpClienteach time — use .NET's built-in factory to manage instances efficiently (prevents socket exhaustion issues).
内容的提问来源于stack exchange,提问作者code4fun

