Skip to main content

Troubleshooting

Credential Issuer errors

401 Unauthorized — "invalid token"

Symptom: The Issuer call returns {"error": "Unauthorized", "detail": "invalid token"}.

Cause: The Bearer token in the Authorization header is invalid, has expired, or the public key used to verify it does not match the one configured in KEYCLOAK_JWKS_URI.

Solution:

  1. Check that the token has not expired (exp claim in the JWT payload).
  2. Verify that KEYCLOAK_JWKS_URI points to the JWKS endpoint of the correct Keycloak realm for the environment you are using.
  3. Obtain a new token from the Keycloak realm and retry the call.

400 Bad Request — "Missing required data or invalid powers"

Symptom: The call to POST /issuance/representative or POST /issuance/employee returns an error about missing claims in the token.

Cause: The Keycloak token does not include all the necessary claims. The Issuer requires at least: organization_identifier, organization, user_identifier, email.

Solution:

  1. Check that the Keycloak client has attribute mappers configured that include organization_identifier, organization, user_identifier, and email in the access_token.
  2. Verify that the user authenticated in Keycloak has those attributes filled in their profile or that the credential IDP maps them correctly from the presented VC.

400 Bad Request — "The requested powers are not authorized for the organization"

Symptom: The powers sent in the POST body are rejected by the Issuer.

Cause: The powers requested in the request body are not authorized by the ISBE Management API for the applicant's organization.

Solution:

  1. Check with ISBE the powers authorized for your organization.
  2. Make sure the request body only includes powers that form a subset of the authorized ones.
  3. Verify that MANAGEMENT_API_URL in the Issuer configuration points to the correct environment.

The QR expires before the user scans it

Symptom: The user tries to scan the QR with their wallet and an expired code error is returned.

Cause: The preauth code expiration time (QR_EXPIRATION_TIME, default 300 seconds) has elapsed.

Solution:

  1. The user must request a new credential issuance to obtain a fresh QR.
  2. If the problem is recurring, the Issuer administrator can increase the value of QR_EXPIRATION_TIME in the configuration.

The credential remains pending indefinitely

Symptom: The IssuedCredential record in the database remains in pending state even though the user scanned the QR.

Possible cause 1: The issuance confirmation was not received to the Issuer's /issuance/notifications endpoint (network error, timeout, incorrect API Key).

Possible cause 2: The service detected an error when verifying the VC (invalid signature, expired VC, issuer not accredited in the TIR).

Solution:

  1. Contact ISBE support to review the issuance service logs.
  2. If the presented VC has cryptographic issues, the user must obtain a new credential from the corresponding issuer.

Credential IDP errors

The user sees "FAILED" on the QR screen

Symptom: Polling returns {"status": "FAILED"} and the page shows an error to the user.

Cause: The verification service rejected the credential presented by the wallet. Possible reasons:

  • The presented VC has expired (validUntil exceeded).
  • The VC signature is invalid (rotated or corrupted key in the DID Document).
  • The VC issuer is not accredited in the TIR of the environment being accessed.
  • The type of VC presented does not match the OID_CREDENTIAL configured in the IDP (IsbePortalLearCredential by default).

Solution:

  1. Check that the wallet's VC is current and was issued by the ISBE Issuer for the correct environment.
  2. Verify that the VC issuer's DID has an active accreditation in the TIR by querying GET <TIR>/v1/issuers/<DID>/attributes.
  3. If the VC has expired, request a new one from the Credential Issuer.

POST /accounts/token returns an OIDC error

Symptom: Keycloak cannot exchange the authorization code for tokens: the /accounts/token endpoint returns an error.

Cause: Keycloak's redirect_uri does not match the Redirect URIs configured in the IDP OIDC client, or the client_id / client_secret are incorrect.

Solution:

  1. Verify the IDP configuration in Keycloak: the Redirect URI must be https://<keycloak-domain>/broker/<idp-alias>/endpoint.
  2. Verify that the OIDC client in the IDP admin panel has exactly that URL registered in Redirect URIs.
  3. Check that Client ID and Client Secret (if applicable) match between Keycloak and the IDP.

User attributes do not arrive correctly in Keycloak

Symptom: The Keycloak token does not include the expected attributes (e.g. organization_identifier is absent).

Cause: The active scope's mappers in the IDP are not correctly configured, or Keycloak's mappers for external IDP attributes are not defined.

Solution:

  1. Review the scope mappers in the IDP admin panel (/admin/). The correct syntax is key = path.to.field (e.g. organization_identifier = credentialSubject.mandate.mandator.organizationIdentifier).
  2. In Keycloak, review the "Mappers" section of the external IDP: there must be one mapper for each attribute you want to arrive in the final access token.

The QR does not appear or the page loads indefinitely

Symptom: When redirecting to the IDP's QR screen, the page does not load correctly or shows a server error.

Possible cause 1: The verification service is unavailable.

Possible cause 2: Error in the IDP database (DATABASE_URL incorrect or PostgreSQL not accessible).

Solution:

  1. Check the IDP's GET /health endpoint: it should return the database health status.
  2. Contact ISBE support if the problem persists.
  3. Review the IDP logs looking for exceptions in the verification session initialization.

Schema and validation errors

The VC fails schema validation

Symptom: When presenting a VC, the verification service returns an error stating the VC is invalid according to the JSON Schema.

Cause: Some field in the VC does not meet the schema requirements (credentialSchema.id). Common causes:

  • mandate.power is an empty array (at least one element is required).
  • mandate.mandatee.employeeId is absent (mandatory field).
  • @context does not include https://www.w3.org/ns/credentials/v2 as the first element.
  • The type array does not include all types in the inheritance chain.

Solution:

  1. Download the JSON Schema from the VC's credentialSchema.id field.
  2. Validate the VC's JWT payload against that schema using a JSON Schema validation tool (e.g. ajv, jsonschema).
  3. Fix the fields that do not comply with the schema and reissue the credential.

termsOfUse.id points to a non-existent accreditation

Symptom: The verifier indicates it cannot find the issuer's accreditation in the TIR.

Cause: The termsOfUse.id field of the VC points to a TIR URL that does not exist or belongs to a different environment.

Solution:

  1. Query the TIR of the correct environment (GET <TIR>/v1/issuers/<DID>/attributes) to obtain the current accreditation hash.
  2. Reissue the credential with the correct termsOfUse.id.
  3. If the issuer's accreditation does not appear in the TIR, contact the ISBE team to regularize the situation.