You are viewing an old version of this page. View the current version.
Compare with Current
View Page History
« Previous
Version 46
Next »
Status codes
The SASIS Regis uses standard http status codes.
The following status codes will generally be used by the API:
Status Code | Description |
---|
200 | Success |
202 | Accepted; Request is valid and business process could be triggered successfully. |
400 | Bad Request; The request data is invalid. |
401 | Unauthorized; The caller does not have sufficient privileges to perform the call. |
403 | Forbidden; The server is refusing the action. |
500 | Internal Server Error; Any unexpected internal failure. |
Referenced Algorithms
Clearing number check digit
The clearing number has the following structure:
- A leading char as check digit
- A four digit sequential number
- A two digit number circle / canton number
The leading char of the clearing number is created and validated as follows:
- Each number is multiplied with its position (calculate from the right end).
- All products are summarized into one sum.
- Modulo 26 of the sum denotes the char in the alphabet (result 0 results in char 'Z').
Example L248519:
(9*1)+(1*2)+(5*3)+(8*4)+(4*5)+(2*6) = 90
90 mod 26 = 12
12th char in the alphabet = L
UID ECH0097 check digit
The ECH0097 enterprise identification number (Unternehmensidentifikationsnummer UID, Numéro d’identification des entreprises IDE, Numero d’identificazione delle imprese IDI) has the following structure:
- ISO-Alpha-3 Code (ISO 3166-1) of Switzerland (CHE)
- 8 digit pseudo random number
- check digit
The check digit is created and validated as follows:
- Each digit of the pseudo-random number is multiplied with a predefined multiplier: 54327654
- All products are summarized into one sum.
- 11 minus Modulo 11 of the sum defines the check digit.
Example CHE-114.617.288:
(1*5)+(1*4)+(4*3)+(6*2)+(1*7)+(7*6)+(2*5)+(8*4) = 124
124 mod 11 = 3
11 - 3 = 8
Authentication / Autorisation
The authentication is based on OpenID Connect, an identity layer on top of OAuth 2.0 and its corresponding flows/grants. For application integration, the resource owner password flow using the OAuth 2.0 password grant is to be used.
The SASIS IAM infrastructure acts a OpenID provider / authorization server.
eyJleHRTcnZJbnRlZ1R5cGUiOiIiLCJnQ2xpZW50SWQiOiIiLCJjcmVhdG9yTmFtZSI6IlVua25vd24gVXNlciAodGhvbWFzLmd1ZW50ZXIpIiwib3V0cHV0VHlwZSI6ImJsb2NrIiwibGFzdE1vZGlmaWVyTmFtZSI6IlVua25vd24gVXNlciAodGhvbWFzLmd1ZW50ZXIpIiwibGFuZ3VhZ2UiOiJlbiIsInVpQ29uZmlnIjoie30iLCJkaWFncmFtRGlzcGxheU5hbWUiOiIiLCJzRmlsZUlkIjoiIiwiYXR0SWQiOiIxMzk0NjA2NTIiLCJkaWFncmFtTmFtZSI6ImFwaV9hY2Nlc3Nfc2VxdWVuY2UiLCJhc3BlY3QiOiIiLCJsaW5rcyI6ImF1dG8iLCJjZW9OYW1lIjoiWlNSIFdlYnNlcnZpY2UiLCJ0YnN0eWxlIjoidG9wIiwiY2FuQ29tbWVudCI6ZmFsc2UsImRpYWdyYW1VcmwiOiIiLCJjc3ZGaWxlVXJsIjoiIiwiYm9yZGVyIjp0cnVlLCJtYXhTY2FsZSI6IjEiLCJvd25pbmdQYWdlSWQiOjEzOTQ2MDYzMCwiZWRpdGFibGUiOmZhbHNlLCJjZW9JZCI6MjYyNjAzNzI2LCJwYWdlSWQiOiIiLCJsYm94Ijp0cnVlLCJzZXJ2ZXJDb25maWciOnsiZW1haWxwcmV2aWV3IjoiMSJ9LCJvZHJpdmVJZCI6IiIsInJldmlzaW9uIjoyLCJtYWNyb0lkIjoiMTBjNWU4Y2UtODgxMi00MDgzLWExOTUtYjNmMjNlZjY4YTY5IiwicHJldmlld05hbWUiOiJhcGlfYWNjZXNzX3NlcXVlbmNlLnBuZyIsImxpY2Vuc2VTdGF0dXMiOiJPSyIsInNlcnZpY2UiOiIiLCJpc1RlbXBsYXRlIjoiIiwid2lkdGgiOiI2MDAiLCJzaW1wbGVWaWV3ZXIiOmZhbHNlLCJsYXN0TW9kaWZpZWQiOjE1NzU4ODgxNzg2NjMsImV4Y2VlZFBhZ2VXaWR0aCI6ZmFsc2UsIm9DbGllbnRJZCI6IiJ9
- The API Client requests the token endpoint from the auth server.
- The token endpoint is returned to the API Client.
- Request an access token from the auth server by providing the following post request parameters:
- grant_type: set to 'password'
- client_id: provided individually by SASIS
- client_secret: provided individually by SASIS
- username: provided individually by SASIS
- password: provided individually by SASIS
- scope: set constantly to 'openid profile email offline_access roles c1s_profile cpr'
- The access token as well as the refresh token is returned to the API Client.
- The specific API resource is called providing the access token in as bearer in the Authorization http header:
'Authorization: Bearer <access token>'
- The API responds to the request.
- Once the access token expired, the previously received refresh token is used to request a new access token from the auth server by providing the following parameters:
- grant_type: set to 'refresh_token'
- client_id: provided individually by SASIS
- client_secret: provided individually by SASIS
- scope: set constantly to 'openid profile email offline_access roles c1s_profile cpr'
- refresh_token: The refresh token received with the last access token.
- A new access token as well as a new refresh token is returned to the API Client.
- The specific API resource is called providing the new access token in as bearer in the Authorization http header:
'Authorization: Bearer <access token>'
- The API responds to the request.
Access token
The access token response contains additional information:
{
"access_token": "MTQ0NjOkZmQ5OTM5NDE9ZTZjNGZmZjI3",
"refresh_token": "GEbRxBNZmQOTM0NjOkZ5NDE9ZedjnXbL",
"token_type": "bearer",
"expires_in": 300,
"scope": "openid profile email offline_access roles c1s_profile cpr"
}
The token itself is a JWT and can therefore be decoded on the JWT website.
The expires_in field defines the validity period of the token in seconds. Afterwards, a new token must be retrieved.
Code samples
A complete c# sample shows how to access one specific API resource (numbers):
Authentication in other languages follows the same procedure.
The following code snippets explain the procedure on a step-by-step basis:
/// <summary>
/// Loads the IAM configuration.
/// </summary>
private async Task<DiscoveryResponse> GetDiscoveryDocumentAsync(CancellationToken ct)
{
using (var client = new HttpClient())
{
var discoveryResponse = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
{
Address = "[AuthorityUrl]"
}, ct).ConfigureAwait(false);
if (discoveryResponse.IsError)
throw new Exception(discoveryResponse.Error);
return discoveryResponse;
}
}
/// <summary>
/// Gets a new token response with a username and password.
/// </summary>
private async Task<TokenResponse> RequestTokenAsync(CancellationToken ct)
{
using (var client = new HttpClient())
{
var discoveryResponse = await GetDiscoveryDocumentAsync(ct).ConfigureAwait(false);
var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
ClientId = "[ClientId]",
ClientSecret = "[ClientSecret]",
UserName = "[UserName]",
Password = "[Password]",
Address = discoveryResponse.TokenEndpoint,
GrantType = OidcConstants.GrantTypes.Password,
Scope = string.Join(" ", _scopes),
}, ct).ConfigureAwait(false);
if (tokenResponse.IsError)
throw new Exception(tokenResponse.Error);
return tokenResponse;
}
}
/// <summary>
/// Gets the access token by either requesting a new token or by using the refresh token of an already existing token.
/// </summary>
private async Task<string> GetAccessTokenAsync(CancellationToken ct)
{
if (_tokenResponse == null)
{
// Creates a new token response
_tokenResponse = await RequestTokenAsync(ct).ConfigureAwait(false);
}
else
{
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
// Parses JWT access token
var jwtSecurityToken = jwtSecurityTokenHandler.ReadToken(_tokenResponse.AccessToken) as JwtSecurityToken;
// The access token might be valid now, but expired the very next millisecond.
// Thus, add a reasonable reserve in minutes for the validity time comparison below.
var comparisionCorrectionInMinutes = 1;
// Compares the access token life time with the current time, modified by the comparison correction value.
if (jwtSecurityToken.ValidTo < DateTime.UtcNow.AddMinutes(comparisionCorrectionInMinutes))
{
// Updates the existing token response
_tokenResponse = await RefreshTokenAsync(_tokenResponse.RefreshToken, ct).ConfigureAwait(false);
}
}
return _tokenResponse.AccessToken;
}
/// <summary>
/// Gets an updated token response by using a refresh token.
/// </summary>
private async Task<TokenResponse> RefreshTokenAsync(string refreshToken, CancellationToken ct)
{
using (var client = new HttpClient())
{
var discoveryResponse = await GetDiscoveryDocumentAsync(ct).ConfigureAwait(false);
var tokenResponse = await client.RequestTokenAsync(new TokenRequest
{
ClientId = "[ClientId]",
ClientSecret = "[ClientSecret]",
Address = discoveryResponse.TokenEndpoint,
ClientCredentialStyle = ClientCredentialStyle.AuthorizationHeader,
GrantType = OidcConstants.GrantTypes.RefreshToken,
Parameters =
{
{ "refresh_token", refreshToken },
{ "scope", string.Join(" ", _scopes) }
}
});
if (tokenResponse.IsError)
throw new Exception(tokenResponse.Error);
return tokenResponse;
}
}
/// <summary>
/// A simple CPR API number search request.
/// </summary>
private async Task<BulkResponse> CprApiSampleRequestAsync(string accessToken, CancellationToken ct)
{
BulkResponse bulkResponse = new BulkResponse();
using (var client = new HttpClient())
{
client.SetBearerToken(accessToken);
var response = await client.GetAsync($"https://[CprBaseUrl]/ApiGateway/api/v1/numbers?searchOptions=Okp&offset=0&limit=10", ct).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
throw new Exception("There was a problem with the request");
string content = await response.Content.ReadAsStringAsync();
if (content != null && content.Length > 0)
{
bulkResponse = JsonConvert.DeserializeObject<BulkResponse>(content);
}
}
return bulkResponse;
}
var accessToken = await GetAccessTokenAsync(ct).ConfigureAwait(false);
var cprApiResponse = await CprApiSampleRequestAsync(accessToken, ct).ConfigureAwait(false);