You are viewing limited content. For full access, please sign in.

Question

Question

API Token Authentication

asked on September 27, 2022

I have been having trouble authenticating to the LF API. I can connect to the repository without a problem on the .NET sample project provided on Github using the LF API CloudAccessKeyString but when I try to authenticate an access key via the JWT with the sample code provided I get the error: 

I have followed the instructions to the letter:
https://developer.laserfiche.com/guide_oauth-service.html

Any thoughts on what could be going wrong would be appreciated

0 0

Answer

SELECTED ANSWER
replied on September 29, 2022

Hi, i'm not sure what the issue would be, but perhaps you can try the below code if you want to get an access token without using the Laserfiche Repository Api Client library.

 

Please use the following Laserfiche Api Client Core NuGet package and provide the servicePrincipalKey and base64EncodedAccesskey. They should be the same values used when you were able to successfully run the .NET sample project.

https://www.nuget.org/packages/Laserfiche.Api.Client.Core/1.2.1

string servicePrincipalKey = "";
string base64EncodedAccesskey = "";

AccessKey accessKey = AccessKey.CreateFromBase64EncodedAccessKey(base64EncodedAccesskey);
TokenClient tokenClient = new TokenClient(accessKey.Domain);
try
{
    var response = await tokenClient.GetAccessTokenFromServicePrincipalAsync(servicePrincipalKey, accessKey);
    Console.WriteLine("apitoken for swagger = " + response.Access_token);
}
catch (ApiException<ProblemDetails> ex)
{
    Console.WriteLine(ex.Result.Title);
    Console.WriteLine(JsonConvert.SerializeObject(ex.Result));
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

 

0 0

Replies

replied on September 28, 2022

Hi, a couple things to double check 

  • Are you calling the correct oauth token endpoint? In the guide, it uses the US cloud url, https://signin.laserfiche.com/oauth/token, but if your Laserfiche account is in CA cloud, then the url should be https://signin.laserfiche.ca/oauth/token instead. For a Laserfiche account in EU cloud, the url should be https://signin.eu.laserfiche.com/oauth/token.
  • In the sample code provided in the guide you linked, check if the JsonWebKey provided to the CreateClientCredentialsAuthorizationJwt function is correct. For reference, when creating the Access Key for your service app in the Developer Console, the JsonWebKey provided to the function should contain the information in the "jwk" portion of the json
    {
    	"customerId": "...",
    	"clientId": "...",
    	"domain": "...",
    	"jwk": {
    		"kty": "...",
    		"crv": "...",
    		"use": "...",
    		"kid": "...",
    		"x": "...",
    		"y": "...",
    		"d": "...",
    		"iat": ...
    	}
    }
    
  • If you continue getting the error, please post the error json response so that we can look into why the error occurred
0 0
replied on September 28, 2022

response error = System.Net.Http.HttpRequestException: Request failed with status code Unauthorized
response content = {"type":"invalid_client","title":"The client_id is invalid or authentication failed.","status":401,"instance":"/token","operationId":"0693561ea73341aa9cebd7a6ac2082c3","traceId":"00-e07b4fca33480b4689f70fa1db377455-d9acabc8fc3a3e4b-00"}
Line 234 successful

apitoken for swagger  = {"type":"invalid_client","title":"The client_id is invalid or authentication failed.","status":401,"instance":"/token","operationId":"0693561ea73341aa9cebd7a6ac2082c3","traceId":"00-e07b4fca33480b4689f70fa1db377455-d9acabc8fc3a3e4b-00"}
 

Here is the error. I checked both of those things you mentioned and they are correct. I am in Canada so my domain changes to .ca and the function GetSigningCredentials requires only the JWK portion of the JSON object to be sent. 

0 0
replied on September 28, 2022

Here is some code to reference from the project. I am using the library RestSharp. 

 

string key = File.ReadAllText(@"LF API CloudAccessKey.json");//ServiceKey downloaded from App Configuration Authentication, placed on same folder as this app
            string token = CreateClientCredentialsAuthorizationJwt(clientId, servicePrincipalKey, new JsonWebKey(key));
            Console.WriteLine(token + "\n");

            var client = new RestClient($"https://signin.laserfiche.ca/oauth/token");
            

            var request = new RestRequest();
            request.Method = Method.Post;

            request.AddHeader("Authorization", $"Bearer {token}");
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("grant_type", "client_credentials");
            request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials", ParameterType.RequestBody);
            request.RequestFormat = DataFormat.Json;

            try
            {
                RestResponse response = client.Execute(request);

                Console.WriteLine("response error = " + response.ErrorException);
                Console.WriteLine("response content = " + response.Content);

                string apiToken = (response.Content);
                
                Console.WriteLine("apitoken for swagger  = " + apiToken);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

0 0
replied on September 28, 2022

Hi, I can see that the "token" being used is partially correct. Could you double check the client id being used is the one associated with the service app's key?

 

Also, I used your exact code and was able to get an access token.

0 0
replied on September 28, 2022

the client Id being used is the same one seen in the developer console which is the same one seen in the clientId value in the JSON object. 
 

0 0
replied on September 28, 2022

will this work with a Laserfiche Cloud DEMO account? 

0 0
replied on September 28, 2022

It sounds like everything is right based on what you described. Sorry, but could you verify this information again?

 

  • The "LF API CloudAccessKey.json" file contains something like this json object where the "kid" value is the same as one seen in the service app's Key ID on the Developer Console 
    {
      "kty": "...",
      "crv": "...",
      "use": "...",
      "kid": "...",
      "x": "...",
      "y": "...",
      "d": "...",
      "iat": ...
    }
    
  • The "clientId" is the one for the service app
  • The "servicePrincipalKey" is for the service account assigned to the service app
  • After creating the token from the CreateClientCredentialsAuthorizationJwt function, could you verify it looks good by decoding it. For example, you could paste the token in this site to verify the information in the token is correct https://jwt.io/
    • The header should contain the same "kid" value as the one on the Developer Console
    • In the payload, verify the client_id is the service app's client id and the client_secret is the "servicePrincipalKey"


And this should work for a Cloud Demo Account since I was using one and you were able to get the .NET sample project to work

0 0
replied on September 28, 2022

Additionally, if the .NET sample project still works for you, could you base64 decode the ACCESS_KEY that you are providing to the project? It should look something like this after base64 decode.

{
	"customerId": "...",
	"clientId": "...",
	"domain": "...",
	"jwk": {
		"kty": "...",
		"crv": "...",
		"use": "...",
		"kid": "...",
		"x": "...",
		"y": "...",
		"d": "...",
		"iat": ...
	}
}

The clientId, key, and oauth endpoint being used by the code you provided should all match.

0 0
replied on September 28, 2022

the JSON file kid matches the key id in the developer console

clientId is the client id as seen on the developer console

servicePrincipalKey is one of the service principal keys 

 

base64 decode of the string provided to the .NET sample project produces the same result as the JSON object. 

 

base64 decode of the token produced by the code - kid is in the header and matches, client id and client secret are in the payload and they match as well

0 0
SELECTED ANSWER
replied on September 29, 2022

Hi, i'm not sure what the issue would be, but perhaps you can try the below code if you want to get an access token without using the Laserfiche Repository Api Client library.

 

Please use the following Laserfiche Api Client Core NuGet package and provide the servicePrincipalKey and base64EncodedAccesskey. They should be the same values used when you were able to successfully run the .NET sample project.

https://www.nuget.org/packages/Laserfiche.Api.Client.Core/1.2.1

string servicePrincipalKey = "";
string base64EncodedAccesskey = "";

AccessKey accessKey = AccessKey.CreateFromBase64EncodedAccessKey(base64EncodedAccesskey);
TokenClient tokenClient = new TokenClient(accessKey.Domain);
try
{
    var response = await tokenClient.GetAccessTokenFromServicePrincipalAsync(servicePrincipalKey, accessKey);
    Console.WriteLine("apitoken for swagger = " + response.Access_token);
}
catch (ApiException<ProblemDetails> ex)
{
    Console.WriteLine(ex.Result.Title);
    Console.WriteLine(JsonConvert.SerializeObject(ex.Result));
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

 

0 0
replied on September 29, 2022

Thank you I was able to use this code to get a successful token 

0 0
replied on September 29, 2022

No problem, glad it worked out

0 0
replied on September 28, 2022 Show version history

Hi Jason, I have duplicated the same result as Brandon.

Here is what I did:

1. A new demo account;

2. A Service user account for testing;

3. Registered a new Service App and then create the Service key

4. Following all the step from https://developer.laserfiche.com/guide_service-principals.html  to generate a JWT use the C# code sample (JWT verified via https://jwt.io/ that decoded as exact same before encoding)

5. Use both Brandon's code and use plain "WebClient" to do a post at "https://signin.laserfiche.ca/oauth/token"  get exactly same error  "401" error

6. Use postman with JWT generated by code sample get the same "401" error

 

So basically it's not working on our end -- could it be account related? let us know.

0 0
replied on September 29, 2022

Hi, could you also try the .NET sample project provided on Github or the sample code I provided above and see if it works for you

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.