Introduction
In order to use the CoreOne Suite Application Interface (API) or to access another application connected via OpenID by means of an API user, an access token must be resolved. This article describes how such an access token can be resolved.
Preconditions
The following preconditions must be fulfilled in order to be able to redeem an Access Token.
1 | Register application | The application from which you want to access the application interface must be registered in the CoreOne Suite and assigned a client_secret. |
2 | API users | You must have a user set up with the permissions to call the desired API function. |
3 | Token Endpoint | You need the URL on which the token endpoint is configured. This looks something like the following: |
Zugriffs-Token lösen (3rd party lib IdentityModel)
The easiest way to solve a valid AccessToken is by using the nuget-packages IdentityModel.
A sample console application can be downloaded here
var disco = await DiscoveryClient.GetAsync(discoUri); var tokenClient = new TokenClient(disco.TokenEndpoint, "client-name", "client-secret"); var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("username", "password", "scopes"); if (tokenResponse.IsError) { throw new Exception(tokenResponse.Error); } return tokenResponse.AccessToken
Detach Access Token (Manual)
If all preconditions are fulfilled, an access token can be resolved via the following steps.
1 | Determine the token endpoint | Call the Discovery Endpoint. private static async Task<string> GetTokenEndpointUri(string discoUri) { using (var httpClient = new HttpClient()) { //Create a simple GET-Request to the Discovery-Uri var discoDoc = await httpClient.GetStringAsync(discoUri); //return the property token_endpoint from GET-Response var discoElement = (dynamic)JsonConvert.DeserializeObject(discoDoc); return (string)discoElement.token_endpoint; } } |
2 | Compiling the parameters | The following parameters must be included in the token request: grant_type → password
|
3 | Query the access token | A simple HTTP post to the previously determined token endpoint can resolve the access token. using (var httpClient = new HttpClient()) { //Use Client-Identifier / Client-Secret for Basic-Authentication httpClient.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(tokenRequest.ClientIdentifier, tokenRequest.ClientSecret); //Create a POST request to the token-endpoint with data in FormUrlEncoded format var tokenResponse = await httpClient.PostAsync(tokenRequest.TokenEndppointUri, new FormUrlEncodedContent(new Dictionary<string, string> { {"grant_type" , "password"}, {"username", "someUserName" }, {"password", "somePassword" }, {"scope", "openid c1s_api roles" })} })); //return the property access_token from POST-Response var tokenResponseDoc = await tokenResponse.Content.ReadAsStringAsync(); var tokenElement = (dynamic)JsonConvert.DeserializeObject(tokenResponseDoc); var result = (string)tokenElement.access_token; } |
Complete example (Manual)
The above simplified example can be found here in complete form.
using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Newtonsoft.Json; namespace ConsoleResourceOwnerFlowRefreshToken { public class Program { public static void Main(string[] args) => MainAsync().GetAwaiter().GetResult(); private static async Task MainAsync() { string tokenEndpoint = null; while (tokenEndpoint == null) { Console.Clear(); Console.WriteLine("Get TokenEndpoint"); try { tokenEndpoint = await GetTokenEndpointUri("https://localhost:5000/.well-known/openid-configuration"); } catch (Exception e) { Console.WriteLine(); Console.WriteLine($"Error: {e}"); Console.WriteLine(); Console.WriteLine("Press q to quit or any other key to retry"); if (char.ToLower(Console.ReadKey().KeyChar) == 'q') return; tokenEndpoint = null; } } var tokenRequest = new TokenRequest { TokenEndppointUri = tokenEndpoint, Scopes = new[] { "openid", "c1s_api", "roles" }, ClientIdentifier = "anyClient", ClientSecret = "anySecret", Username = "someUserName", Password = "someUserPassword" }; do { Console.Clear(); try { Console.WriteLine($"Token-Endpoint: {tokenEndpoint}"); Console.WriteLine(); var token = await GetToken(tokenRequest); Console.WriteLine(token ?? "null"); } catch (Exception e) { Console.WriteLine($"Error: {e}"); } Console.WriteLine(); Console.WriteLine("Press q to quit or any other key to renew token"); } while (char.ToLower(Console.ReadKey().KeyChar) != 'q'); } private static async Task<string> GetToken(TokenRequest tokenRequest) { using (var httpClient = new HttpClient()) { //Use Client-Identifier / Client-Secret for Basic-Authentication httpClient.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(tokenRequest.ClientIdentifier, tokenRequest.ClientSecret); //Create a POST request to the token-endpoint with data in FormUrlEncoded format var tokenResponse = await httpClient.PostAsync(tokenRequest.TokenEndppointUri, new FormUrlEncodedContent(new Dictionary<string, string> { {"grant_type" , "password"}, {"username", tokenRequest.Username }, {"password", tokenRequest.Password }, {"scope", string.Join(" ", tokenRequest.Scopes)} })); //return the property access_token from POST-Response var tokenResponseDoc = await tokenResponse.Content.ReadAsStringAsync(); var tokenElement = (dynamic)JsonConvert.DeserializeObject(tokenResponseDoc); return (string)tokenElement.access_token; } } private static async Task<string> GetTokenEndpointUri(string discoUri) { using (var httpClient = new HttpClient()) { //Create a simple GET-Request to the Discovery-Uri var discoDoc = await httpClient.GetStringAsync(discoUri); //return the property token_endpoint from GET-Response var discoElement = (dynamic)JsonConvert.DeserializeObject(discoDoc); return (string)discoElement.token_endpoint; } } } public class TokenRequest { public string TokenEndppointUri { get; set; } public string ClientIdentifier { get; set; } public string ClientSecret { get; set; } public string Username { get; set; } public string Password { get; set; } public string[] Scopes { get; set; } } }
Postman
In Postman, a token can also be solved directly. For this, the type OAuth 2.0 must be selected under Authorization.