Skip to main content

OIDC Authentication

How CloudForge authenticates users in front of, or inside, a deployed application.

Authentication modes​

authMode (enum AuthMode in cloudforge-core/src/main/java/com/cloudforge/core/enums/):

ValueWhere authentication happens
none (default)Nowhere; the application's own login applies.
alb-oidcThe Application Load Balancer authenticates requests before forwarding them. Works for any application that allows it; the application sees the user through the x-amzn-oidc-* headers.
application-oidcThe application runs the OIDC flow itself through its OidcIntegration (for example the Jenkins oic-auth plugin). Supports group-to-role mapping and provider logout.

The legacy value jenkins-oidc is accepted as an alias for application-oidc.

Each application declares the modes it supports (ApplicationSpec.getSupportedAuthModes()); see the catalog. When a deployment requests an unsupported mode, CloudForge switches to the application's recommended mode and prints a warning.

Both OIDC modes require HTTPS. When authMode is alb-oidc or application-oidc, CloudForge sets enableSsl: true. Without domain or certificateArn, the certificate is issued by a stack-owned AWS Private CA for the load balancer DNS name; browsers show a warning because the CA is not publicly trusted.

With alb-oidc, every path is protected unless the application declares protectedPaths() (for example WordPress protects only /wp-admin/* and /wp-login.php), minus any publicPaths() it declares.

Quick start​

Cognito, application-level:

{
"authMode": "application-oidc",
"cognitoAutoProvision": true,
"cognitoDomainPrefix": "my-app",
"cognitoMfaEnabled": true,
"cognitoInitialAdminEmail": "admin@example.com"
}

Cognito, ALB-level:

{
"authMode": "alb-oidc",
"cognitoAutoProvision": true,
"cognitoDomainPrefix": "my-app"
}

External OIDC provider:

{
"authMode": "application-oidc",
"oidcProvider": "external-idp",
"oidcIssuer": "https://login.example.com",
"oidcAuthorizationEndpoint": "https://login.example.com/oauth2/v1/authorize",
"oidcTokenEndpoint": "https://login.example.com/oauth2/v1/token",
"oidcUserInfoEndpoint": "https://login.example.com/oauth2/v1/userinfo",
"oidcClientId": "my-client-id",
"oidcClientSecretName": "my-app/oidc/client-secret"
}

CloudForge Manager as the identity provider:

{
"authMode": "application-oidc",
"oidcProvider": "cloudforge-manager",
"cloudforgeManagerIssuerUrl": "https://manager.example.com",
"oidcClientId": "my-client-id",
"oidcClientSecretName": "my-app/oidc/client-secret"
}

Provider selection​

For application-oidc, the provider is chosen from the configured keys in this order:

  1. Cognito: cognitoAutoProvision is true, or cognitoUserPoolId is set.
  2. IAM Identity Center (SAML): autoProvisionIdentityCenter is true and ssoInstanceArn is set.
  3. CloudForge Manager: oidcProvider is cloudforge-manager and cloudforgeManagerIssuerUrl is set.
  4. External provider: oidcIssuer is set.

If oidcProvider is unset or none when an OIDC mode is requested, it defaults to cognito and Cognito auto-provisioning is enabled unless cognitoUserPoolId is given.

Configuration reference​

Core​

KeyDefaultDescription
authModenonenone, alb-oidc, or application-oidc
oidcProvidernone (becomes cognito for OIDC modes)cognito, identity-center, external-idp, or cloudforge-manager

Cognito user pool (auto-provisioned)​

KeyDefaultDescription
cognitoAutoProvisionfalse (true for OIDC modes without cognitoUserPoolId)Create a user pool in the stack
cognitoDomainPrefix{stackName}-authHosted UI domain prefix. Lowercased and sanitized, then suffixed with -{stackName}
cognitoUserPoolName{stackName}-usersUser pool name
cognitoMfaEnabledfalseRequire MFA. Set it explicitly for production deployments
cognitoMfaMethodbothtotp, sms, or both
cognitoSelfSignupEnabledsecurity profile defaultAllow hosted UI self-registration
cognitoCreateGroupstrueCreate an admin group and a user group
cognitoAdminGroupName{applicationId}-AdminsAdmin group name
cognitoUserGroupName{applicationId}-UsersUser group name
cognitoInitialAdminEmailadmin@{domain}First admin user; Cognito emails a temporary password
cognitoInitialAdminPhone—E.164 phone number for SMS MFA

Production user pools use RemovalPolicy.RETAIN; reuse a retained pool with cognitoUserPoolId.

SMS MFA requires an Amazon SNS SMS spending limit above the account default of USD 0.

Existing Cognito user pool​

KeyDescription
cognitoUserPoolIdExisting user pool ID
cognitoAppClientIdExisting app client ID
cognitoDomainPrefixExisting hosted UI domain prefix

External provider (external-idp)​

KeyDescription
oidcIssuerIssuer URL (https://)
oidcAuthorizationEndpointAuthorization endpoint
oidcTokenEndpointToken endpoint
oidcUserInfoEndpointUserInfo endpoint
oidcClientIdClient ID registered with the provider
oidcClientSecretNameSecrets Manager secret name holding the client secret

CloudForge Manager (cloudforge-manager)​

KeyDescription
cloudforgeManagerIssuerUrlPublic base URL of the Manager install; endpoints are derived from it
oidcClientIdClient ID registered in Manager
oidcClientSecretNameSecrets Manager secret name holding the client secret

IAM Identity Center​

KeyDescription
autoProvisionIdentityCenterProvision the Identity Center application
ssoInstanceArnIdentity Center instance ARN
ssoGroupId, identityCenterGroupName, ssoTargetAccountIdGroup assignment

IAM Identity Center and the SAML-based integrations (including Metabase's) are incomplete and should not be relied on for production deployments.

Application integrations​

OidcIntegration implementations live in cloudforge-core/src/main/java/com/cloudforge/core/oidc/. The general applications with an integration are:

ApplicationIntegration classMethod
JenkinsJenkinsOidcIntegrationoic-auth plugin, JCasC
GitLabGitLabOidcIntegrationOmniAuth OpenID Connect
GrafanaGrafanaOidcIntegrationgeneric_oauth environment variables
Mattermost TeamMattermostGitLabOidcIntegrationGitLab OAuth settings (MM_GITLABSETTINGS_*); no single logout
Mattermost EnterpriseMattermostOidcIntegrationNative OpenID Connect (MM_OPENIDSETTINGS_*)
MetabaseMetabaseSamlIntegrationSAML
CloudForge ManagerCloudForgeManagerOidcIntegrationBuilt-in OIDC client

CMS platforms have their own integrations (WordPressOidcIntegration, DrupalOidcIntegration, and so on); see CMS.md.

Gitea, SonarQube, Harbor, Nexus, Superset, Drone, Prometheus, Vault, PostgreSQL, and Redis have no integration and support only authMode: none.

Jenkins​

With application-oidc, CloudForge writes /var/jenkins_home/casc_configs/oidc.yaml and sets CASC_JENKINS_CONFIG. The generated configuration:

  • uses the oic security realm with serverConfiguration.manual endpoints, client secret from ${JENKINS_OIDC_CLIENT_SECRET}, and logoutFromOpenidProvider: true;
  • sets endSessionUrl to the Cognito /logout endpoint with client_id and logout_uri, because Cognito's logout endpoint does not follow the standard end_session_endpoint parameters (oic-auth-plugin#95);
  • reads groups from the cognito:groups claim (JMESPath-escaped);
  • when groups are enabled, applies a projectMatrix strategy: the admin group gets Overall/Administer, the user group gets build, configure, create, read, and workspace permissions, and anonymous access is denied;
  • when cognitoCreateGroups is false, uses loggedInUsersCanDoAnything with anonymous read disabled;
  • enables the Audit Trail plugin, logging to /var/jenkins_home/logs/audit.log.

Interfaces​

OidcConfiguration carries provider settings (getProviderType(), getIssuerUrl(), the endpoint getters, getJwksUri(), getLogoutEndpoint(), getClientId(), getClientSecretArn(), getRedirectUrl(), getScopes(), claim getters, group names, usePkce() (default true)).

OidcIntegration adapts it to an application: getEnvironmentVariables(config), getConfigurationFile(config), getConfigurationFilePath(), getUserDataCommands(config, context), getPostDeploymentInstructions(), getOidcCallbackPath(), and capability flags (supportsAlbOidc(), supportsApplicationOidc(), supportsCognito(), supportsIdentityCenterSaml()).

Cognito reference​

EndpointURL
Authorizationhttps://{domain}.auth.{region}.amazoncognito.com/oauth2/authorize
Tokenhttps://{domain}.auth.{region}.amazoncognito.com/oauth2/token
UserInfohttps://{domain}.auth.{region}.amazoncognito.com/oauth2/userInfo
Logouthttps://{domain}.auth.{region}.amazoncognito.com/logout
Issuerhttps://cognito-idp.{region}.amazonaws.com/{userPoolId}
JWKShttps://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

Groups are delivered in the cognito:groups claim. IAM Identity Center uses different endpoints and a groups claim; the two are not interchangeable.

Client secrets​

Client secrets are stored in AWS Secrets Manager and read by the container or EC2 user data at startup. They are not written into the CloudFormation template or deployment context.

Troubleshooting​

redirect_uri_mismatch — the callback URL does not match the Cognito app client. Check that domain and subdomain (or the load balancer DNS name when using a Private CA) match the URL users open, and that the URL is HTTPS.

Browser certificate warning — expected with a Private CA certificate. Import the CA certificate into the client trust store for testing, or configure a public domain.

User can sign in but has no permissions — add the user to the admin or user Cognito group.

Jenkins logs — on Fargate, the application log group is /aws/ecs/{stackName}/fargate/{securityProfile} for dev and staging; production log groups are retained and get a CloudFormation-generated name. On EC2, see /var/log/jenkins/jenkins.log.

References​