Documentation
JWT Authentication with an API in the DHCS Developer Portal
Overview
This document outlines how to authenticate using OAuth 2.0 to retrieve a JWT (JSON Web Token) and how to use that token to call secured APIs hosted on the DHCS API Gateway. It includes JWT token retrieval examples with curl and C#. Also, once the token is retrieved it includes examples in both curl and C# for leveraging the token to access an API.
Curl example
Step 1: Retrieve an Access Token Using Client Credentials
Use the following curl command to request an access token from the authorization server:
curl -X POST "https://login.mes.dhcs.ca.gov:443/am/oauth2/alpha/access_token" \
-u <client_id>:<client_secret> \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" -s
Parameters
| Parameter | Description |
|---|---|
client_id |
Your registered OAuth client ID |
client_secret |
Your OAuth client secret |
grant_type |
Must be set to client_credentials |
Content-Type |
Must be application/x-www-form-urlencoded |
Example successful response
{
"access_token": "<access_token>",
"scope": "profile",
"token_type": "Bearer",
"expires_in": 43199
}
Step 2: Use the Access Token to Call Secured APIs
Include the token in the Authorization header when calling APIs on the Gateway:
curl -X GET \
https://example-api.gateway.mes.dhcs.ca.gov/api/v1/desired-endpoint \
-H "Authorization: Bearer <access_token>"
Replace <access_token> with the actual token retrieved in Step 1.
Example API call
ACCESS_TOKEN=<access_token>
curl -X GET \
https://example-api.gateway.mes.dhcs.ca.gov/api/v1/health \
-H "Authorization: Bearer $ACCESS_TOKEN"
Determining the URL for the API you want to consume
WAIT! Where did example-api.gateway.mes.dhcs.ca.gov come from in the example? How would I find or build the URL for the API I want to consume?
The API’s base URL (scheme and host) is shown at the top of the API Details page. To call a specific endpoint, append the path from the Swagger documentation to this base URL.
Building the correct URL for your API
- Find the base URL (scheme + host):
This is shown at the top of the API Details page in the DHCS Developer Portal. - Find the endpoint path:
Use the Swagger documentation for the API.
Each operation (GET, POST, etc.) has a path (e.g.,/api/v1/Health). - Combine them:
Concatenate the base URL (1) and the endpoint path (2).
Example:- Base URL:
https://example-api.gateway.mes.dhcs.ca.gov - Endpoint path:
/api/v1/Health - Full URL:
https://example-api.gateway.mes.dhcs.ca.gov/api/v1/Health
- Base URL:
.NET example
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
...
public class TestAuth
{
...
[Fact]
public async Task TestGetJwtTokenAndAuthenticatedEndpointResult()
{
// Arrange
var pingOauthUrl = "https://login.mes.dhcs.ca.gov:443/am/oauth2/alpha/access_token";
var clientId = "<client_id>";
var clientSecret = "<client_secret>";
var endpointUrl = "https://ess-api.gateway.mes.dhcs.ca.gov/api/v1/health";
// Act
var jwtToken = await GetJwtToken(pingOauthUrl, clientId, clientSecret);
var authenticatedEndpointResult = await GetAuthenticatedEndpointAsync(new HttpClient(), jwtToken, endpointUrl);
// Assert
Assert.NotNull(jwtToken);
Assert.NotNull(authenticatedEndpointResult);
}
public static async Task<string?> GetJwtToken(string pingOauthUrl, string clientId, string clientSecret)
{
using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
var basicAuth64 = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}"));
using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, pingOauthUrl)
{
Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
})
};
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth64);
httpRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using var pingJwtResponse = await httpClient.SendAsync(httpRequestMessage);
var pingJwtResponseBody = await pingJwtResponse.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower // snake_case to PascalCase
};
var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(pingJwtResponseBody, jsonSerializerOptions);
return tokenResponse?.AccessToken;
}
// Mapping class for jwt token response from Ping Oauth
private sealed class TokenResponse
{
public string? AccessToken { get; set; }
public int ExpiresIn { get; set; }
public string? TokenType { get; set; }
public string? Scope { get; set; }
}
public static async Task<string> GetAuthenticatedEndpointAsync(HttpClient http, string accessToken, string endpointUrl, CancellationToken ct = default)
{
using var req = new HttpRequestMessage(HttpMethod.Get, endpointUrl);
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using var resp = await http.SendAsync(req, ct);
var body = await resp.Content.ReadAsStringAsync(ct);
if (!resp.IsSuccessStatusCode)
throw new HttpRequestException($"Request failed with {(int)resp.StatusCode}: {body}");
return body;
}
}
Conclusion
By following this guide, developers can authenticate securely and call DHCS API Gateway endpoints using bearer tokens. Expect JWT tokens to expire regularly but as this document demonstrates, generating a new JWT token is straightforward. Please consult Ping’s OAuth response expires_in field for more specifics when acquiring the JWT token.