Skip to main content

Use an interaction hook

Authorise the interaction hook redirect

Your interaction hook component must be publicly available, and you must therefore apply access controls to protect it from unauthorised access. Sovrin interaction hook integration supports a JWT (HS256)-based authorisation scheme to help enable this. 

 When Sovrin redirects the end user to your interaction hook component, it will also include a JWT object as a session_token query parameter:

https://example.com/mywebapp?session_token=GENERATED_JWT

Your interaction hook component should verify the JWT object using the interaction hook secret to make sure that the request is legitimate. This secret can be obtained from the response when you make a request to configure an interaction hook.

Libraries like Jose can be used for node servers, as shown in the following example:

import { jwtVerify } from "jose";

// Retrieved from URL session_token query parameter
const jwt = "YOUR_JWT";

// Recieved when you created an interaction hook on your tenant
const secret = Buffer.from("SHARED_SECRET", "base64");

const issuer = "https://api.sovrin.one";

// The URL of your interation hook
const audience = "https://example.com/mywebapp";

const verifiedJwt = jwtVerify(
token,
secret,
{ issuer, audience }
);

 - The JWT is stored as a string in the jwt variable.

  • The secret variable contains the secret key that was returned when you configured your interaction hook. 

  • The issuer and audience variables are used to define the expected JWT object issuer and audience, and are retrieved from your configured interaction hook.

If the verification is successful, the function will return the decoded JWT payload. If the verification fails, it means the JWT payload should not be used and an error will be thrown.

Decoded JWT payload 

Here is an example of a verified and decoded JWT payload with values that can be extracted by your interaction hook component:

{
"state": "hJvfiSp3eEGybd-KmL8ja",
"scopes": [
"ldp_vc:CourseCredential"
],
"claims": {
"email": "test@sovrin.one"
},
"authenticationProvider": {
"url": "https://myidentityprovider.auth0.com",
"subjectId": "user|123456789"
},
"redirectUrl": "https://api.sovrin.one/core/v1/oauth/interaction/hJvfiSp3eEGybd-KmL8ja/interactionhook/callback",
"sub": "a44a7f92-c61e-48a0-88b6-863eeeb58394",
"aud": "https://example.com/mywebapp",
"iss": "https://api.sovrin.one",
"iat": 1673910963,
"exp": 1673911263
}
  • state: A unique value associated with each interaction hook session.

  • scopes: Scopes retrieved from user authentication workflow.

  • claims: User claims defined when you configured your interaction hook. .

  • authenticationProvider: A provider that the user is authenticated with. 

    • url: URL of the authentication provider. 

    • subjectId: Subject Identifier of the end user with this authentication provider.

  • redirectUrl: Url to redirect to when users complete the interactions hook journey.

  • sub: Sovrin end user subject identifier.

  • aud: Interactions hook URL.

  • iss: Your Sovrin tenant.

  • iat: Issued at (Epoch Unix timestamp).

  • exp: Expires at (Epoch Unix timestamp).

Interaction hook response

Once the end user completed the custom journey, they need to be redirected back to Sovrin to complete the credential issuance workflow.  The redirect URL can be found in the session token JWT payload above. The issuer must generate and sign a new JWT token and include it as a query parameter with the redirect.

You can optionally use this token to include new or updated claims you wish to merge with the existing end-user claims on Sovrin. These claims will be available during issuance and will not be persisted on your tenant unless configured to do so using the claimsToPersist field. This field is empty by default, meaning no claims are persisted by default.

Here is an example of using the same Jose library to sign a new JWT session token:

import { SignJWT } from "jose";

const secret = Buffer.from(
"<SHARED_SECRET>",
"base64"
);

const jwt = await new SignJWT({
iss: "https://example.com/mywebapp",
aud: "https://api.sovrin.one",
state: "hJvfiSp3eEGybd",
claims: { myNewClaim: "foobar" }
claimsToPersist: []
})
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
.setIssuedAt()
.setExpirationTime("1m")
.sign(secret);
  • secret is the same value used for authorizing the interaction hook above.

  • iss and aud can be retrieved from the original session token by swapping the values:

    • iss from the original token will be the aud in the response token.

    • aud from the original token will be the iss in the response token.

  • state is a unique value associated with each interaction hook session. It can be extracted from the session token JWT payload above. 

  • claims can be used to transfer any new claims from the interaction hook journey.

  • claimsToPersist indicates transferred claims that will be persisted on Sovrin.

  • setProtectedHeader is used to set the protected JWT header. In this case, it includes the algorithm (alg:"HS256") and the token type (typ:"JWT").

  • setIssuedAt is used to set the "issued at" (iat) claim to the current time. This indicates when the JWT was signed.

  • setExpirationTime is used to set the JWT expiration time (exp). In this case, it is set to expire 1 minute after it is issued.

The resulting signed session token (JWT) should be added as a query parameter to the redirect URL:

https://api.sovrin.one/core/v1/oauth/interaction/hJvfiSp3eEGyb/interactionhook/callback?session_token=...  

This it the URL that the user will be sent to once the interaction hook journey is completed.