Self-hosting

Create the Microsoft Entra ID application secret for AWS

This guide is for the customer administrator preparing the AWS Secrets Manager secret for a Markyard hosting whose selected identity provider is Microsoft Entra ID.

Customer guideIdentity administrator

Do not use this page for an Auth0 hosting. Complete the Microsoft Entra ID application setup first.

Before you begin

You need:

  • the deployment AWS account and Region;
  • permission to create a Secrets Manager secret there;
  • the Entra Directory (tenant) ID, Application (client) ID, and client secret Value from the Markyard Web app registration; and
  • a stable Markyard organization identifier such as org_acme.

The organization identifier is a Markyard data boundary, not the Entra tenant ID. Choose it once and never change it after users or documents exist.

1. Generate the encryption keys

On a trusted administrative workstation, generate 64 random bytes encoded as unpadded base64url:

openssl rand -base64 64 | tr '+/' '-_' | tr -d '=\n'

Generate a separate 32-byte key for provider-token encryption:

openssl rand -base64 32 | tr '+/' '-_' | tr -d '=\n'

Copy both results directly into the secret document. Do not put them in a ticket, chat, source-control repository, or shared command history.

2. Build the secret document

Create the following JSON document in a secure temporary editor and replace every uppercase placeholder:

{
  "authCookieKey": "GENERATED_COOKIE_KEY",
  "providerTokenKeysJson": "{\"active\":\"v1\",\"keys\":{\"v1\":\"GENERATED_PROVIDER_TOKEN_KEY\"}}",
  "oidcProvidersJson": "[{\"id\":\"entra\",\"display_name\":\"Microsoft Entra ID\",\"organization_id\":\"org_CUSTOMER\",\"issuer_url\":\"https://login.microsoftonline.com/ENTRA_TENANT_ID/v2.0\",\"client_id\":\"ENTRA_APPLICATION_CLIENT_ID\",\"client_secret\":\"ENTRA_CLIENT_SECRET_VALUE\",\"scopes\":[\"openid\",\"profile\",\"email\",\"offline_access\",\"User.ReadBasic.All\"],\"require_email_verified\":false,\"directory\":{\"kind\":\"entra\",\"excluded_account_suffixes\":[\"-Admin\",\" Admin\"]}}]"
}

Important details:

  • oidcProvidersJson is a string containing a JSON array, so its inner quotation marks remain escaped.
  • The array contains exactly one provider.
  • Keep id as entra; the deployment configuration must use the same provider ID.
  • Put the tenant GUID in the issuer URL. Do not use common, organizations, or consumers.
  • Supply the client secret Value, not its Secret ID.
  • Keep require_email_verified disabled because Entra ID does not reliably provide the standard OIDC email_verified claim.
  • Do not add extra top-level keys.

Validate the JSON locally with a security-approved JSON tool without sending it to an online formatter.

Markyard searches users on behalf of the signed-in user. On the existing Markyard Web app registration, add Microsoft Graph Delegated User.ReadBasic.All. Markyard also supports delegated User.Read.All for tenants that have already consented that broader permission; move to User.ReadBasic.All when practical. Markyard requests offline_access so it can refresh the delegated Graph access token.

The same permission covers profile pictures, which Markyard reads with the signed-in user's own delegated token. Accounts without a picture fall back to that person's initials. No extra permission or consent step is needed.

Microsoft recommends granting the least-privileged permissions an application needs. Review the current descriptions and consent requirements in the Microsoft Graph permissions reference.

The provider configuration enables this behavior and can hide administrative accounts from sharing:

{
  "kind": "entra",
  "excluded_account_suffixes": ["-Admin", " Admin"]
}

excluded_account_suffixes is optional. Markyard compares each configured suffix case-insensitively with the Entra display name and with the local part of the mail and user-principal-name fields. Matching accounts are omitted from people search and cannot be resolved for a new share. The setting does not revoke access that was granted previously.

Markyard does not request group permissions and does not expose Entra group sharing. Provider access and refresh tokens remain encrypted on the server and are never sent to the browser.

3. Store the secret in AWS

In the deployment account and Region:

  1. Open AWS Secrets Manager and select Store a new secret.
  2. Select Other type of secret.
  3. Open Plaintext and paste the complete outer JSON object.
  4. Use the AWS managed Secrets Manager key, or select the customer-managed KMS key named in your deployment design.
  5. Name the secret for the installation, for example markyard/production/application.
  6. Do not configure automatic rotation for this compound secret. Coordinate application credential rotation with a deployment and sign-in check.
  7. Store the secret and copy its complete ARN, including AWS's six-character suffix.

AWS cautions that secret values placed directly in shell commands can be recovered from shell history or process inspection. The console or a security-approved file-based AWS CLI workflow avoids putting the value on the command line. See Create an AWS Secrets Manager secret.

Delete the temporary plaintext document securely after confirming that the secret is stored and recoverable by authorized operators.

4. Complete the deployment configuration

Set the deployment configuration values to:

{
  "auth": {
    "providerId": "entra",
    "applicationSecretArn": "COMPLETE_SECRET_ARN"
  }
}

When the secret uses a customer-managed KMS key, also add its complete key ARN as applicationSecretKmsKeyArn.

Return to Deploy Markyard in your AWS account to validate, review, and deploy the stacks.

Rotate credentials

For an Entra client-secret rotation:

  1. Create a replacement secret before the current secret expires and copy its Value.
  2. Update only the relevant client-secret value inside oidcProvidersJson; preserve the cookie key, provider ID, issuer, tenant, and organization identifier.
  3. Save a new Secrets Manager secret version.
  4. Run the deployment diff and deployment so ECS starts a new task definition referencing the current secret.
  5. Verify browser sign-in and people search.
  6. Delete the superseded Entra secret after validation.

Troubleshooting

  • Provider mismatch: the provider object and deployment configuration must both use entra.
  • OIDC discovery failure: verify the tenant GUID and /v2.0 issuer URL.
  • Invalid client secret: confirm that the stored value is the secret Value, not its Secret ID, and that it has not expired.
  • Directory 401 or 403: confirm delegated User.ReadBasic.All (preferred) or User.Read.All, organizational consent, the configured scopes, tenant ID, and client ID; then reconnect the signed-in user.
  • Initials where a profile picture is expected: confirm the person has a picture set in Microsoft 365 or Entra ID, then check the same delegated permission as directory search — avatars use that token. Profile pictures are unavailable in Azure AD B2C tenants.
  • Secret validation failure: confirm the outer object has exactly three keys, the inner provider array contains exactly one object, the cookie key decodes to 64 bytes, and the active provider-token key decodes to 32 bytes.