Sign in with NobleID on WordPress
Add Sign in with NobleID to a WordPress site with the OpenID Connect Generic Client plugin.
- Written for
- The OpenID Connect Generic Client plugin (slug
daggerhart-openid-connect-generic), version 3.11.3 or later. Earlier versions have no Issuer field, so every NobleID sign-in fails: update first. - Tested
- We checked the plugin's requests against a test server. The plugin itself has not been run against NobleID.
Register on NobleID
- In Dashboard → OAuth apps, register a confidential app. You need two-step login on your NobleID to do this.
- Add this redirect URI, with your own host:Copy the value the plugin's settings page shows. With Alternate Redirect URI on, it is
https://example.org/wp-admin/admin-ajax.php?action=openid-connect-authorizehttps://example.org/openid-connect-authorizeinstead. - Tick these scopes: OpenID (always on), Profile
profile, Emailemail. The platform asks for these, and sign-in stops if it asks for a scope the app does not have. - Copy the client ID and the client secret. The secret is shown once.
The app works at once. Until NobleID verifies it, people see a “not verified” notice on the consent screen.
Plugin settings
In Settings → OpenID Connect Client:
| Field | Value |
|---|---|
| Login Type | OpenID Connect button on login form |
| Client ID | nbcl_your_client_id |
| Client Secret Key | nbcs_your_client_secret (or set it in wp-config.php, below) |
| OpenID Scope | openid email profile |
| Login Endpoint URL | https://www.nobleid.org/oauth/authorize |
| Userinfo Endpoint URL | https://id.nobleid.org/oauth/userinfo |
| Token Validation Endpoint URL | https://id.nobleid.org/oauth/token |
| End Session Endpoint URL | leave empty to end only the WordPress session, or https://www.nobleid.org/oauth/logout to end the NobleID session too (see below) |
| JWKS URI | https://id.nobleid.org/.well-known/jwks.json |
| Issuer | https://id.nobleid.org |
| ACR values | leave empty |
| Identity Key | sub |
| Nickname Key | preferred_username |
| Email Formatting | {email} |
| Display Name Formatting | {name} |
| Identify with User Name | unticked |
| Enable Refresh Token | unticked |
| Disable SSL Verify | unticked |
| Allow Internal IDP | unticked |
| Link Existing Users | unticked (see below) |
| Create user if does not exist | your choice |
Set the Issuer field. The login endpoint is on www.nobleid.org, but the issuer is https://id.nobleid.org. With the Issuer field empty, the plugin takes the issuer from the login endpoint's host and every sign-in fails.
Set the JWKS URI. The plugin always checks the ID token's iss, aud and exp. Only with the JWKS URI does it also check the signature. Do not run without it.
The plugin can also import settings from https://id.nobleid.org/.well-known/openid-configuration (Import from Discovery Document). The imported values are not saved until you click Save Changes. Then check that Issuer and JWKS URI are filled. The import can also fill End Session Endpoint URL: empty it unless you want sign-out to end the NobleID session too.
To keep the secret out of the database, define it in wp-config.php:
define( 'OIDC_CLIENT_ID', getenv( 'NOBLEID_CLIENT_ID' ) );
define( 'OIDC_CLIENT_SECRET', getenv( 'NOBLEID_CLIENT_SECRET' ) );Existing WordPress users
With Link Existing Users ticked, the plugin matches an existing account by email address. It does not check email_verified first, so someone could put an administrator's address on a NobleID account and sign in as that administrator. Keep it unticked and link existing accounts by hand.
The plugin records the NobleID sub on the WordPress user and finds returning users by it. The Identity Key only picks the username for new accounts. sub is unique and never changes. preferred_username reads better, but it can change and can collide with an existing username.
What the plugin does
- It is a confidential client using
client_secret_postandstate. It sends no PKCE and no nonce. NobleID allows both for confidential clients. - It sends an extra
scopeparameter on the token request. NobleID ignores it. - It does not check the
issresponse parameter. It checks the ID token'sissagainst the Issuer field. - With End Session Endpoint URL empty, signing out ends the WordPress session only. With it set, the plugin also sends the person to NobleID, which asks them to confirm, then returns them to the page WordPress shows after sign-out.
With the login button, that page is https://example.org/wp-login.php?loggedout=true&wp_lang=en_US, and the language part follows each user's language. NobleID returns people only to an exact address listed in the app's sign-out return URLs, and otherwise shows an error. Set one fixed address with a small plugin, and list it in the NobleID dashboard:
<?php
// Return everyone to the home page after sign-out. List exactly this address
// (with the trailing slash) as a sign-out return URL on your NobleID app.
// Priority below 99, the plugin's own filter, which then sends it to NobleID.
add_filter( 'logout_redirect', function () {
return home_url( '/' );
}, 10 );Fill the profile from NobleID
| NobleID claim | WordPress field | Scope |
|---|---|---|
given_name | First Name | profile |
family_name | Last Name | profile |
preferred_username | Nickname (Nickname Key) | profile |
name | Display name (Display Name Formatting {name}) | profile |
email | Email (Email Formatting {email}) | email |
website | Website, with the code below | profile |
orcid | A user meta field, with the code below | orcid |
The plugin fills the first five when it creates the account. On each later sign-in it calls the openid-connect-generic-update-user-using-current-claim action with the claims, so a small plugin can fill what is still empty:
For orcid, add orcid to the plugin's OpenID Scope field and tick ORCID iD on your app.
<?php
/*
* Plugin Name: NobleID profile fields
* Description: Fills empty profile fields from Sign in with NobleID. Never overwrites what the person edited.
*/
add_action( 'openid-connect-generic-update-user-using-current-claim', function ( $user, $claims ) {
if ( empty( $user->user_url ) && ! empty( $claims['website'] ) ) {
wp_update_user( array( 'ID' => $user->ID, 'user_url' => esc_url_raw( $claims['website'] ) ) );
}
// Sent only when the person proved the iD by signing in to ORCID.
if ( ! empty( $claims['orcid'] ) && ! empty( $claims['orcid_verified'] ) && ! get_user_meta( $user->ID, 'orcid', true ) ) {
update_user_meta( $user->ID, 'orcid', esc_url_raw( $claims['orcid'] ) );
}
}, 10, 2 );Every claim, and how to fill a profile without overwriting what people edit: Fill your app's profile from NobleID.
Before you go live
- Sign in once with your own NobleID. People need a first and last name on their NobleID profile to sign in; NobleID asks for it if it is missing.
- Key accounts on
sub. Link to an existing account by email only whenemail_verifiedis true. - Remove any localhost redirect URIs from the app.
- Keep the client secret out of version control.
NobleID values
| Issuer | https://id.nobleid.org |
| Discovery URL | https://id.nobleid.org/.well-known/openid-configuration |
| Authorization endpoint | https://www.nobleid.org/oauth/authorize |
| Token endpoint | https://id.nobleid.org/oauth/token |
| Userinfo endpoint | https://id.nobleid.org/oauth/userinfo |
| JWKS URL | https://id.nobleid.org/.well-known/jwks.json |
| Revocation endpoint | https://id.nobleid.org/oauth/revoke |
| End-session endpoint | https://www.nobleid.org/oauth/logout |
| ID token signing | ES256 |
Sources
Something here does not match what you see? Email info@nobleid.org.