omniauth-honin

An OmniAuth strategy for authenticating users via Honin — the privacy-first identity provider.

Works with Honin Cloud (honin.id), self-hosted Honin instances, and Rails apps that mount the honin-engine in IDP mode.

Installation

gem "omniauth-honin"

Configuration

Honin Cloud

# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :honin,
    ENV["HONIN_CLIENT_ID"],
    ENV["HONIN_CLIENT_SECRET"],
    jwks_uri: "https://honin.id/.well-known/jwks.json"
end

jwks_uri is optional but recommended for production — it verifies the JWT signature on every login. Without it the access token is decoded without signature verification.

Self-hosted instance (root-mounted)

Point client_options: { site: } at your server. Everything else is the same.

provider :honin,
  ENV["HONIN_CLIENT_ID"],
  ENV["HONIN_CLIENT_SECRET"],
  client_options: { site: "https://auth.acme.co" },
  jwks_uri: "https://auth.acme.co/.well-known/jwks.json"

Self-hosted instance (sub-path mount)

If the Honin engine is mounted under a path — e.g. mount HoninEngine, at: "/auth" — set base_path to that path. The strategy uses it to construct the OAuth endpoints and to verify the iss claim in the JWT.

provider :honin,
  ENV["HONIN_CLIENT_ID"],
  ENV["HONIN_CLIENT_SECRET"],
  client_options: { site: "https://id.acme.co" },
  base_path: "/auth",
  jwks_uri: "https://id.acme.co/auth/.well-known/jwks.json"

base_path is not needed for Honin Cloud or any instance where the engine is at the root.

Requesting additional scopes

Honin supports email, profile, timezone, and locale. Scopes must be registered on your Honin Application. The default is "email profile".

provider :honin,
  ENV["HONIN_CLIENT_ID"],
  ENV["HONIN_CLIENT_SECRET"],
  scope: "email profile timezone locale"

Auth hash

After successful authentication, request.env["omniauth.auth"] contains:

{
  "provider": "honin",
  "uid": "abc123xyz456def789",
  "info": {
    "account_type": "standard",
    "name": "Jane Doe",
    "email": "jane@example.com",
    "email_verified": true,
    "timezone": "America/Toronto",
    "locale": "en"
  },
  "credentials": {
    "token": "eyJhbGciOiJSUzI1NiIs...",
    "token_type": "Bearer",
    "expires": true,
    "expires_at": 1700000000
  },
  "extra": {
    "raw_info": { "...JWT claims..." },
    "granted_scopes": ["email", "profile"],
    "required_scopes": ["email"]
  }
}

account_type is "anonymous" for anonymous users; scope-dependent fields (name, email, etc.) are absent.

granted_scopes reflects what the user actually granted. required_scopes are scopes the Honin Application marked as non-deniable.

How it works

  1. Strategy generates a PKCE code verifier/challenge pair (S256).
  2. User is redirected to the Honin authorize endpoint.
  3. User authenticates and grants consent.
  4. Honin redirects back with an authorization code.
  5. Strategy exchanges the code (with PKCE verifier) for a signed JWT access token.
  6. Strategy decodes the JWT to extract user claims — no separate userinfo request needed.

Development

bundle install
bundle exec rake test
bundle exec standardrb

License

MIT — see LICENSE.