Authentication¶
PikoCI supports two authentication methods: local username/password and OAuth/OIDC single sign-on. Both can be active simultaneously, and users can link multiple OAuth identities to a single PikoCI account.
Overview¶
- Local auth uses username/password stored in PikoCI's database (bcrypt-hashed).
- OAuth/OIDC auth delegates authentication to an external identity provider (GitHub, Google, GitLab, Keycloak, etc.).
- Multiple OAuth providers can be active at the same time.
- Local auth can be disabled once at least one OAuth provider is configured.
- OAuth users are auto-created on first login with a profile completion step.
- Existing local users can link their OAuth identity from their profile.
Configuring OAuth Providers¶
Prerequisites¶
-
Set the
--external-urlflag on the PikoCI server to the public URL users access (e.g.,https://ci.example.com). This is used to build OAuth callback URLs.Or via environment variable:
-
Log in as a global admin.
Adding a Provider via the Admin UI¶
Go to the user menu (top right) and click Authentication. From there:
- Click Add Provider.
- Select a Provider Template (GitHub, Google, GitLab, etc.) to auto-fill URLs, scopes, and type. Or select Other for manual configuration.
- The Callback URL is displayed automatically. Copy it and paste it into your provider's redirect URI settings.
- Fill in your Client ID and Client Secret.
- Click Create Provider.
The provider appears on the login page immediately, with no server restart needed.
Provider Types¶
PikoCI supports two provider types:
| Type | When to use | What you configure |
|---|---|---|
| OIDC | Google, GitLab, Keycloak, Azure AD, any OpenID Connect provider | Just the Issuer URL. Endpoints are auto-discovered. |
| OAuth2 | GitHub, Bitbucket, custom providers without OIDC discovery | Auth URL, Token URL, and Userinfo URL manually |
GitHub (OAuth2)¶
GitHub does not support OIDC, so use the OAuth2 type.
1. Create a GitHub OAuth App¶
- Go to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.
- Fill in:
- Application name:
PikoCI(or whatever you like) - Homepage URL:
https://ci.example.com - Authorization callback URL:
https://ci.example.com/auth/oauth/github/callback
- Application name:
- Click Register application.
- Copy the Client ID.
- Click Generate a new client secret and copy it.
2. Add to PikoCI¶
In the Authentication admin page, click Add Provider, select GitHub from the template (all URLs and settings are pre-filled), then paste your Client ID and Client Secret.
Note
Set Username Claim to login to use the GitHub username. Set it to email to use the email prefix instead.
Warning
GitHub OAuth Apps do not restrict which users can authorize. Any GitHub user can sign in unless you restrict access at the network level or use a GitHub Organization App. See Restricting Who Can Sign In.
Google (OIDC)¶
Google supports OpenID Connect, so use the OIDC type.
1. Create Google OAuth Credentials¶
- Go to the Google Cloud Console.
- Select or create a project.
- Go to APIs & Services → OAuth consent screen. Set User type to Internal to restrict to your Google Workspace domain (recommended). External allows any Google account.
- Go to APIs & Services → Credentials → Create Credentials → OAuth client ID.
- Set Application type to Web application.
- Under Authorized redirect URIs, add:
https://ci.example.com/auth/oauth/google/callback - Click Create and copy the Client ID and Client Secret.
2. Add to PikoCI¶
In the Authentication admin page, click Add Provider, select Google from the template (issuer URL and settings are pre-filled), then paste your Client ID and Client Secret.
GitLab (OIDC)¶
Works with both GitLab.com and self-hosted GitLab.
1. Create a GitLab Application¶
- Go to GitLab → Admin Area → Applications → New Application (or User Settings → Applications for non-admin).
- Fill in:
- Name:
PikoCI - Redirect URI:
https://ci.example.com/auth/oauth/gitlab/callback - Scopes:
openid,email,profile
- Name:
- Click Save application and copy the Application ID and Secret.
2. Add to PikoCI¶
In the Authentication admin page, click Add Provider, select GitLab from the template, then paste your Client ID and Client Secret. For self-hosted GitLab, change the Issuer URL to your instance's URL.
Keycloak (OIDC)¶
1. Create a Keycloak Client¶
- In Keycloak Admin Console, go to your realm → Clients → Create client.
- Set Client ID to
pikoci. - Set Client authentication to On (confidential).
- Under Valid redirect URIs, add:
https://ci.example.com/auth/oauth/keycloak/callback - Save and go to the Credentials tab to copy the Client secret.
2. Add to PikoCI¶
In the Authentication admin page, click Add Provider, select Keycloak from the template, then set the Issuer URL to https://keycloak.example.com/realms/your-realm and paste your Client ID and Client Secret.
Microsoft / Azure AD (OIDC)¶
1. Register an Application in Azure AD¶
- Go to Azure Portal → Azure Active Directory → App registrations → New registration.
- Set Redirect URI to
https://ci.example.com/auth/oauth/microsoft/callback(type: Web). - After creation, copy the Application (client) ID and Directory (tenant) ID.
- Go to Certificates & secrets → New client secret and copy the value.
2. Add to PikoCI¶
In the Authentication admin page, click Add Provider, select Microsoft from the template, then set the Issuer URL to https://login.microsoftonline.com/{tenant-id}/v2.0 (replace {tenant-id} with your Azure AD tenant ID) and paste your Client ID and Client Secret.
Login Flow¶
When OAuth providers are configured, the login page shows the local login form followed by OAuth provider buttons below an "or" divider.
New Users¶
- User clicks Log in with GitHub (or another provider).
- PikoCI redirects to the provider's authorization page.
- User authenticates at the provider.
- Provider redirects back to PikoCI with an authorization code.
- PikoCI exchanges the code for an access token and fetches user info.
- If this is the first login, PikoCI shows a Complete Your Profile form pre-filled with the username (from the provider) and full name.
- User reviews/edits and submits. A PikoCI account is created and linked to the OAuth identity.
- User is logged in.
Returning Users¶
- User clicks Log in with GitHub.
- Same redirect flow.
- PikoCI finds the existing link and logs the user in directly (no profile form).
Restricting Who Can Sign In¶
PikoCI itself does not filter which users from a provider can sign in. Any user who successfully authenticates with the provider can create a PikoCI account. You should configure access restrictions at the provider level.
Here's how for each provider:
| Provider | How to restrict access |
|---|---|
| In Google Cloud Console → OAuth consent screen, set User type to Internal. Only users in your Google Workspace organization can authenticate. | |
| GitLab | Self-hosted GitLab: only users with GitLab accounts can authenticate. GitLab.com: restrict the application to group members under Admin → Applications. |
| Keycloak | Only users in the configured realm can authenticate. Use realm roles, groups, or client scopes to restrict further. |
| Azure AD | Tenant-scoped by default. Only users in your Azure AD tenant can authenticate. For multi-tenant apps, configure Supported account types to restrict. |
| GitHub | GitHub OAuth Apps allow any GitHub user to authorize. To restrict: create a GitHub Organization App under your org's settings and enable Request user authorization (OAuth) during installation, or use GitHub's IP allow lists. Alternatively, create users manually in PikoCI first and have them link their GitHub accounts from their profile (no auto-provisioning). |
Warning
If you use GitHub as your only OAuth provider without additional restrictions, any GitHub user can create a PikoCI account. Consider keeping local auth enabled and managing users manually, or restricting at the network level.
Account Linking¶
Existing local users can link OAuth identities from Profile → Linked Accounts:
- Go to Profile and click the Linked Accounts tab.
- Click Link GitHub (or another provider).
- Authenticate at the provider.
- The account is linked. You can now log in with either method.
To unlink, click the Unlink button next to the provider.
Warning
You cannot unlink a provider if it is your only authentication method. Set a local password first or link another provider before unlinking.
Setting a Local Password for OAuth Users¶
OAuth users are created without a local password. To enable local login:
- Go to Profile → Password tab.
- Since no password has been set yet, the "Current Password" field is hidden. Enter your new password and confirm it.
- After setting a password, the "Current Password" field will appear for future changes.
This allows logging in with either OAuth or username/password.
Admin: Auth Settings¶
Disabling Local Auth¶
Global admins can disable local username/password login from the Authentication admin page by toggling Enable local username/password login off.
Warning
Local auth cannot be disabled if any user relies solely on local password authentication. All users must have at least one OAuth provider linked before local auth can be turned off.
Managing Providers¶
From the Authentication admin page, you can:
- Add new providers using preset templates or manual configuration
- Edit existing providers (client secret is preserved if left empty)
- Enable/disable providers without deleting them
- Delete providers
Warning
You cannot disable or delete a provider if any user relies on it as their only authentication method (no local password and no other OAuth links). The affected username is shown in the error message.
Changes take effect immediately, with no server restart needed.
API Endpoints¶
Unauthenticated¶
| Method | Path | Description |
|---|---|---|
GET |
/auth/methods |
List enabled providers and local auth status |
GET |
/auth/oauth/{canonical} |
Start OAuth flow (redirects to provider) |
GET |
/auth/oauth/{canonical}/callback |
Handle provider callback |
POST |
/auth/oauth/complete-profile |
Complete profile for first-time OAuth login |
Authenticated¶
| Method | Path | Description |
|---|---|---|
GET |
/profile/linked-accounts |
List linked OAuth accounts |
DELETE |
/profile/linked-accounts/{canonical} |
Unlink an OAuth account |
Admin (Global Admin)¶
| Method | Path | Description |
|---|---|---|
GET |
/admin/oauth-providers |
List all providers |
POST |
/admin/oauth-providers |
Create a provider |
PUT |
/admin/oauth-providers/{canonical} |
Update a provider |
DELETE |
/admin/oauth-providers/{canonical} |
Delete a provider |
GET |
/admin/auth-settings |
Get auth settings |
PUT |
/admin/auth-settings |
Update auth settings |
Security¶
- CSRF protection: Each OAuth flow uses a unique random state parameter with a 5-minute expiration.
- Token security: OAuth callback tokens are short-lived (5 minutes) and single-use.
- Client secrets: Stored in the database (same security model as pipeline secrets). Never exposed in API responses.
- Callback URLs: Built from the
--external-urlflag to prevent open redirect attacks. - Lockout prevention: PikoCI prevents actions that would lock users out of their accounts. Disabling local auth, disabling/deleting a provider, or unlinking an account are all blocked if any user would be left with no way to log in.
Session Lifetime¶
The --session-lifetime flag controls how long a user session remains valid after login. By default it is 0, meaning sessions never expire (backward compatible).
When set, a JWT exp claim is added to all session tokens. After the session expires, the user must re-login. The flag accepts Go duration syntax plus day/week/month/year units (e.g. 24h, 7d, 30d, 1M).
Password changes immediately invalidate all existing sessions for that user. Admin password resets also invalidate the user's sessions. This is done via a generation counter (token_gen) embedded in the JWT. When the counter doesn't match the database, the session is rejected.
See also: Roles & Permissions · API Tokens · Server Configuration