Authentication and authorization

Authentication

Access to the API is restricted, and requires authentication with HelseId so that we can know who is calling the API.

To authenticate, a bearer token needs to be provided as a header in the HTTP request. The bearer token must be obtained from HelseId. There are two ways of obtaining such a token, and they are described in detail below:

  • M2M login with HelseId
  • Personal login with HelseId

Authorization

Some parts of the API require that the HelseId user belongs to the organization that owns the HerId in Addresseregisteret.

  • Reading any Profile is open to everyone, and does not require authorization, only that the user is logged in with HelseId.
  • Editing a Profile requires that the user belongs to the organization that owns the HerId of the Profile.
  • Creating and reading an Agreement requires that the user belongs to the organization that owns one of the HerIds involved in the Agreement.

How to obtain and use a Machine to machine HelseId token

A m2m (machine to machine) token is the primary way an EPJ system will authenticate with the CPPA API. This token contains an Organization number, which is used to determine which resources can be accessed (authorization). The bearer of this token can change the Profile, and view/create Agreements for any communication party belonging to the Organization in the address registry.

Set up a HelseId Client through Selvbetjening

  • Read up on how to create a client configuration for your organization in HelseId.
    • In production this requires the organzation to delegate access through Altinn.
    • In the test environment you can configure which organization you want to represent in the Selvbetjening portal.
  • Log on to the Selvbetjening portal
  • Select Dine klientsystemer to configure your client systems.
    • If your client system is already configured here and it supports API calls, you may add "CPPA REST API Public" to its supported services.
    • Otherwise, add a new client system, set it to support API calls, and add "CPPA REST API Public" to its supported services.
  • Now, select Ta i bruk HelseId from the left menu to create a client configuration for an instance of your system.
    • Create a new client configuration (Ny klientkonfigurasjon)
    • Choose the client system that you just configured as the Fagsystem. If using the test environment, fill in the Organization number that your health care system will act on behalf of here.
    • Choose CPPA REST API Public as the service to consume.
    • Complete the rest of the wizard to issue and download a JSON Web Key, that will be used later to authenticate.
    • It is also possible to upload your own JSON Web Key here, which is a much more secure option than having it issued by us.

Request a token

Now that HelseId knows about your client configuration, your application may request a bearer token from HelseId at any time. This is achieved by posting a request to HelseId's token endpoint. This request must be authenticated by your application by signing a JWT (Json Web Token) with the JWK (Json Web Key) issued in the previous step. This mechanism is called Client assertion.

Example token request (C#, .NET 6+)

  • First, find your ClientId, and your JWK. If you downloaded the configuration file from Selvbetjening, open the json file, and find the values of clientId and privateJwk.
  • Add the following NuGet packages:
      <PackageReference Include="IdentityModel" Version="6.1.0" />
      <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.30.0" />
      <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.30.0" />
    
  • Substitute your clientId and privateJwk into the following example. :
    using System.IdentityModel.Tokens.Jwt;
    using IdentityModel.Client;
    using Microsoft.IdentityModel.Tokens;
    
    const string clientId = "15f46f78-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Insert your client id here
    const string privateJwk = "{\u0022d\u0022:\u0022PXvMfT1d2hNSzpTip.........."; // Insert your private jwk here
    const string tokenEndpoint = "https://helseid-sts.test.nhn.no/connect/token";
    const string scopeName = "nhn:cppa/access";
    
    ClientCredentialsTokenRequest CreateClientAssertionsRequest()
    {
        var request = new ClientCredentialsTokenRequest
        {
            ClientId = clientId,
            Address = tokenEndpoint,
            Scope = scopeName,
            GrantType = IdentityModel.OidcConstants.GrantTypes.ClientCredentials,
            ClientCredentialStyle = ClientCredentialStyle.PostBody,
            ClientAssertion = new ClientAssertion
            {
                Type = IdentityModel.OidcConstants.ClientAssertionTypes.JwtBearer,
                Value = CreateJwtToken()
            }
        };
        return request;
    }
    
    string CreateJwtToken()
    {
        var tokenIssuedAtEpochTimeSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    
        var signingCredentials = new SigningCredentials(new JsonWebKey (privateJwk), SecurityAlgorithms.RsaSha512);
        var header = new JwtHeader(signingCredentials);
        var payload = new JwtPayload
        {
            [JwtRegisteredClaimNames.Iss] = clientId,
            [JwtRegisteredClaimNames.Sub] = clientId,
            [JwtRegisteredClaimNames.Aud] = tokenEndpoint,
            [JwtRegisteredClaimNames.Exp] = tokenIssuedAtEpochTimeSeconds + 60,
            [JwtRegisteredClaimNames.Nbf] = tokenIssuedAtEpochTimeSeconds,
            [JwtRegisteredClaimNames.Iat] = tokenIssuedAtEpochTimeSeconds,
            [JwtRegisteredClaimNames.Jti] = Guid.NewGuid().ToString("N"),
        };
    
        var token = new JwtSecurityToken(header, payload);
        var serializedToken = new JwtSecurityTokenHandler().WriteToken(token);
        return serializedToken;
    }
    
    ClientCredentialsTokenRequest request = CreateClientAssertionsRequest();
    TokenResponse response = await new HttpClient().RequestClientCredentialsTokenAsync(request);
    
    if (response.IsError)
    {
        Console.WriteLine($"Error: {response.Error} - {response.ErrorDescription}");
    }
    else
    {
        Console.WriteLine("Bearer: " + response.AccessToken);
    }
    

Use the token

Now that you have the access token, making an authenticated request is as simple as adding the token as a header.

  • In C#, it could be done like this:
    var cppaHttpClient = new HttpClient
    {
        BaseAddress = new Uri("https://cppa.test.grunndata.nhn.no"),
    
    };
    cppaHttpClient.SetBearerToken(response.AccessToken); // Add the bearer token to all requests made through this HttpClient.
    
    var agreementResponse = await cppaHttpClient.GetAsync("AgreementSummaries/8139673"); // Substitute the HerId for a CommunicationParty under your organization in AR.
    
    agreementResponse.EnsureSuccessStatusCode();
    Console.WriteLine(await agreementResponse.Content.ReadAsStringAsync());
    

How to obtain and use a Personal HelseId token

Obtaining a personal token requires manual input from the user, and is not suited for use by applications. The CPPA API still supports personal tokens in the Test environment only, for testing purposes and for manual exploration.

The personal user must already be a user in the address registry, and the user must have permission to edit an organization in the address registry.

The easiest way to obtain a personal bearer token, is through Swagger UI:

  1. Open Swagger UI: https://cppa.test.grunndata.nhn.no/swagger/index.html
  2. Click the Authorize padlock in the top right corner
  3. Client id and Client secret should be filled out already. Select the scope cppa/access, and click Authorize.
  4. Choose an IDP to authenticate with. Choosing "Test IDP" will let you pick any personal identifier. Choose one that has "AR Administrator" permissions on the communication party you want to administer CPP/CPA for.
  5. If everything went well you may now close the Auth dialog, and use Swagger to perform operations on one of the protected end points, such as /AgreementSummaries/herId.
  6. If the bearer token is needed for another application, it may be extracted from swagger: After authenticating and making a request, check out the Curl section under Responses. It contains a line saying -H 'authorization: Bearer eyJhb...... Everything after the word Bearer on this line is the bearer token.