The IBM Security Verify WebAuthn Relying Party Server for Swift is based on the Vapor framework and exposes endpoints that proxies OAuth and FIDO2 requests to IBM Security Verify from web and mobile clients.
The resource links in the prerequisites explain and demonstrate how you create a new tenant and automate the application and FIDO2 configuration used by the Relying Party Server.
-
Create a free trial tenant here: https://www.ibm.com/account/reg/us-en/signup?formid=urx-30041.
You'll need to have an IBMid but this can be done at the same time.
This link explains setting up your tenant: https://docs.verify.ibm.com/verify/docs/signing-up-for-a-free-trial
-
Create an API client on the trial tenant. See this configuration guide for instructions.
Ensure the API client has the following entitlements:
- Read identity providers
- Manage application lifecycle
- Read application configuration
- Manage second-factor authentication method configuration
-
Clone the relying party repository. Run this command in a Terminal window:
git clone https://github.com/ibm-security-verify/webauthn-relying-party-server.gitModify the
config.jsonto use the client identifier and client secret from the API client created in the previous step.The
relyingPartyHostnameis the Docker host where you'll run the relying party server.Below is a sample of
config.json.{ "tenantUrl":"https://example.verify.ibm.com", "clientSecret":"abc123", "clientId":"abc123-a1b2-4567-a1b2-c3d4e5f6", "appName": "Passkey Starter Kit", "relyingPartyHostname": "example.com" }Use the
starter-kit.pyto create the application and a FIDO2 relying party on your tenant.Run this command to create the application and a FIDO2 relying party:
python3 starter-kit.py -f config.jsonThe output of
starter-kit.pyis an.env.envfile which can be used to configure the relying party server environment variables. The.envfile will be located in the same folder wherestarter-lit.pyis executed from.
The relying-party-server requires several environment variables to launch.
The platform flag indicates if the relying party server is IBM Security Verify (ISV) or IBM Security Verify Access (ISVA). For example:
PLATFORM=ISV
(OPTIONAL) When PLATFORM=ISVA, the AUTH_SESSION allows the relying party server to parse JSON data from the /v1/signin response to generate an authenticated session. The availble values are:
| Name | Description |
|---|---|
| EAI | Requires the FIDO2 mediator to provide additional credential information in credentialData JSON payload. |
| TOKEN | This is the default value if AUTH_SESSION has not (or an invalid value) been provided. For a token to be returned, it requires the FIDO2 mediator to inject access_token into the responseData element of the JSON payload. |
| COOKIE | Returns the response from the FIDO assertion/result endpoint back to the calling client. |
See IBM Security Verify Access FIDO Mediation for more information.
This is a string to represent the JSON for Apple to establish a secure association between domains and your app. The following JSON code represent the contents of a simple association:
{
"webcredentials":{
"apps":[
"ABCDE12345.com.example.app"
]
}
}
The JSON content should be minified when assigned to the environment variable. For example:
APPLE_APP_SITE_ASSOC={"webcredentials":{"apps":["ABCDE12345.com.example.app"]}}
In addition, your iOS mobile app requires an assoicated domain entry that references the relyingPartyHostname. For example:
webcredential:example.com
See Supporting associated domains for more information.
This is a string to represent the JSON for Google to associate login credentials between an app and website. The following JSON code represent the contents of a simple assetlink format:
[{
"relation": ["delegate_permission/common.get_login_creds"],
"target": {
"namespace": "web",
"site": "https://example.com"
}
},
{
"relation": ["delegate_permission/common.get_login_creds"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": [
"DE:AD:BE:EF:****"
]
}
}]
The JSON content should be minified when assigned to the environment variable. For example:
GOOGLE_ASSET_LINKS=[{"relation":["delegate_permission/common.get_login_creds"],"target":{"namespace":"web","site":"https://example.com"}},{"relation":["delegate_permission/common.get_login_creds"],"target":{"namespace":"android_app","package_name":"com.exampl.app","sha256_cert_fingerprints":["DE:AD:BE:EF:****"]}}]
See Google digital asset links for more information.
This is the unique identifier (UUID) that is created when the FIDO2 service is created in IBM Security Verify. For example:
FIDO2_RELYING_PARTY_ID=634cd513-dc6a-5e28-06fg-40c3dc81a79e
See Retrieve the list of relying party configurations for more information or Look up Relying Party ID.
This is the unique client identifier and confidential client secret that the relying party server uses internally to establlished an authenticated session with the FIDO2 and factors endpoints. For example:
API_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
API_CLIENT_SECRET=a1b2c3d4
See FIDO2 for more information.
This is the unique client identifier and confidential client secret that the relying party server uses internally to establlished an authenticated session with the OIDC token endpoints. For example:
AUTH_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
AUTH_CLIENT_SECRET=a1b2c3d4
See Client Credentials for more information.
The base URL is the fully qualified hostname of your tenant. For example:
BASE_URL=https://example.verify.ibm.com
(OPTIONAL) Enable proxy requests to the relying party server to be forwarded to host defined by BASE_URL. For example:
HTTP_PROXY=https://proxy.example.verify.ibm.com:8888
NOTE: Authenticated proxy is supported by setting the environment variable as:
HTTP_PROXY=https://username:password@proxy.example.verify.ibm.com:8888
(OPTIONAL) Add an additional certificate to the trust store for TLS request validation. For example:
ROOT_CA=t4Ck1jbktkQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
NOTE: The
ROOT_CAvalue must be base64 encoded from Privacy Enhanced Mail (PEM) certificate text.
(OPTIONAL) Output log messages for diagnostic purposes. Below are the acceptable values and descriptions.
| Name | Description |
|---|---|
| TRACE | Appropriate for messages that contain information normally of use only when tracing the execution of a program. |
| DEBUG | Appropriate for messages that contain information normally of use only when debugging a program. |
| INFO | Appropriate for informational messages. |
| NOTICE | Appropriate for conditions that are not error conditions, but that may require special handling. |
| WARNING | Appropriate for messages that are not error conditions, but more severe than notice. |
| ERROR | Appropriate for error conditions. |
| CRITICAL | Appropriate for critical error conditions that usually require immediate attention. |
NOTE: Default is the
INFOlogging level. When run with the production environment,NOTICEis used to improve performance.
Returns the JSON content representing the APPLE_APP_SITE_ASSOC environment variable.
Used when the user has an existing account with a password executing an ROPC request to token endpoint. Below is a sample request payload:
{
"username": "anne_johnson@icloud.com",
"password": "a1b2c3d4"
}
If successful, the response format is as follows:
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
Allows a new account to be created where ownership of an email is validated. Below is a sample request payload:
{
"name": "Anne Johnson",
"email": "anne_johnson@icloud.com"
}
If successful, the response format is as follows:
{
"expiry": "2022-11-28T12:26:34Z",
"correlation": "1719",
"transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d"
}
Validate the one-time password generated by the signup. Below is a sample request payload:
{
"transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d",
"otp": "12345"
}
If successful, the response format is as follows:
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
Registers a new public-key credential for a user. Below is a sample request payload:
{
"nickname": "John's iPhone",
"clientDataJSON": "eyUyBg8Li8GH...",
"attestationObject": "o2M884Yt0a3B7...",
"credentialId": "VGhpcyBpcyBh..."
}
If successful, the response status a 201 Created.
The
access_tokenmust be presented in the request authorization header. Authenticated session-cookies can also be passed in the request headers. For example:Authorization: Bearer NLL8EtOJFdbPiwPwZA
401 Unauthorizedwill result otherwise.
Generates a new challenge to perform a WebAuthn registrations or verifications.
Verification (assertion)
Below is a sample request payload for a assertion (signin):
{
"type": "assertion"
}
If successful, the response format is a JSON structure based on Web Authentication: An API for assertion generation (PublicKeyCredentialRequestOptions) as follows:
{
"rpId": "example.com",
"timeout": 240000,
"challenge": "3W9xV1-n6Qvvs9y0YrAr5MpNNba8Q9czsGH4hRdGFwk"
}
Registration (attestation)
Below is a sample request payload for an attestation:
{
"displayName": "Anne's iPhone",
"type": "attestation"
}
If successful, the response format is a JSON structure based on Web Authentication: An API for credential creation (PublicKeyCredentialCreationOptions) as follows:
{
"rp": {
"id": "example.com",
"name": "IBM Cloud Relying Party"
},
"user": {
"id": "ePGatpTNRBaoHdQ",
"name": "anne",
"displayName": "Anne's iPhone"
},
"timeout": 240000,
"challenge": "g9yz-s_rsH4c_ulfLujO96U1wybV_Zut5tQeoKIcmtk",
"excludeCredentials": [],
"extensions": {},
"authenticatorSelection": {},
"pubKeyCredParams": [
{
"alg": -7,
"type": "public-key"
},
{
"alg": -257,
"type": "public-key"
}
]
}
The
access_tokenmust be presented in the request authorization header. For example:Authorization: Bearer NLL8EtOJFdbPiwPwZA
401 Unauthorizedwill result otherwise.
Validates a public-key credential for a user with an existing registration. Below is a sample request payload:
{
"clientDataJSON": "eyUyBg8Li8GH...",
"authenticatorData": "o2M884Yt0a3B7...",
"credentialId": "VGhpcyBpcyBh...",
"signature": "OP84jBpcyB...",
"userHandle": "ePGatpTNR..."
}
If successful, the response format is as follows:
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
The access_token can be used to make requests to other custom endpoints in the relying party server project.
Vapor supports several deployment options. The relying-party-server includes a dockerfile to build an image via docker-compose build. For alternate hosting, refer to the Vapor Docs.
This package contains code licensed under the MIT License (the "License"). You may view the License in the LICENSE file within this package.