Standards-first FAPI 2.0 for Go. OpenID Certified™, hardened, separately conformant client, authorization-server and resource-server engines, built on one rigorously tested protocol core — so you build against the security profile instead of reverse-engineering it yourself.
FAPI 2.0 (Financial-grade API) is the OpenID Foundation's security profile for OAuth 2.0 and OpenID Connect, used by open banking, open finance and other high-assurance API ecosystems to mandate protections — sender- constrained tokens, request integrity, strong client authentication — that plain OAuth leaves optional. Getting PAR, DPoP, JAR/JARM, mTLS or private_key_jwt, and RAR/CIBA all correct by hand is a significant amount of security-critical work; FAPIgo does that work once, as tested and OIDF-certified Go packages.
This isn't a stricter default you can opt out of: legacy patterns FAPI 2.0
and RFC 9700 identify as insecure — the implicit/hybrid response types,
client_secret_basic/client_secret_post authentication — aren't
configuration options that happen to be off, they simply aren't
implemented. server only ever accepts response_type=code, and
ClientAuthMethod is a closed enum of private_key_jwt and the mTLS
variants.
- FAPI 2.0 Security Profile Final + Message Signing Final
- PAR (RFC 9126) · DPoP (RFC 9449) · mTLS client auth & cert-bound tokens (RFC 8705)
- private_key_jwt client authentication
- JAR / JARM · RAR (RFC 9396) · CIBA (poll & ping delivery)
- OpenID Federation 1.0 (trust chains, automatic client registration, trust marks)
- OpenID Certified™ for OP, RP and FAPI-CIBA OP conformance profiles — see below
OpenID Certified™ by Oscar Sanderson to the FAPI 2.0 OP, FAPI 2.0 RP (both Security Profile Final + Message Signing Final), FAPI 2.0 OP Client Credentials Grant Type, and FAPI-CIBA OP conformance profiles of the OpenID Connect™ protocol, as tested for FAPIgo 0.25.0 — not merely a self-run pass against the live suite, but a result submitted to and published by the OpenID Foundation. This is a statement of tested conformance, not an OIDF endorsement of FAPIgo generally. See conformance/README.md#oidf-certification for the full list of certified profiles and links to each official listing.
⚠ Work in progress. FAPIgo is under active development. APIs, package structure, and behavior may change without notice. We recommend waiting for the v1.0 release before considering it for production use.
Requires Go 1.26.6+ (per go.mod's go directive).
go get github.com/idfoundry/fapigo
import (
"github.com/idfoundry/fapigo/client"
"github.com/idfoundry/fapigo/server"
"github.com/idfoundry/fapigo/resource"
)(Go module paths are lowercased; the GitHub repository itself is IDFoundry/FAPIgo.)
client (relying party), server (authorization server) and resource
(resource server / token verification) are independent public packages
with distinct constructors, configuration and workflow APIs — there is no
generic API that tries to behave as more than one role. They share a
rigorously tested internal protocol core (JOSE, DPoP, PAR, PKCE, JARM,
request objects, client assertions, canonicalization) without sharing
role-level types or behaviour.
See GETTING_STARTED.md for a full walkthrough of standing up an authorization server and resource server end to end, including a runnable configuration you can start from.
storage/memstore and keys/ephemeral provide in-memory, non-durable
implementations of every interface server needs (client repository,
transaction/grant/replay/access-token stores, key manager, client key
source) — for local development and testing only, never production —
so integrating server doesn't require writing real persistence and
key management from scratch just to see it run. server.RecommendedLimits()
and server.RecommendedAlgorithms() do the same for Config's algorithm
and duration fields, each grounded in a specific FAPI 2.0 Security
Profile Final or RFC 9449 requirement where one exists.
Access tokens can be issued as self-contained JWTs (RFC 9068 — the
default, server.JWTAccessTokens/resource.JWTAccessTokens) or as
opaque, storage-backed values (server.OpaqueAccessTokens/
resource.OpaqueAccessTokens) — FAPI 2.0 doesn't mandate a format, so
this is a deployment's own choice, not something the library imposes.
OpenID Connect identity (an ID token) is likewise optional, not
assumed: server issues one alongside the access token exactly when
the granted scope includes "openid", and client populates
TokenSet.IDToken/Subject/IDTokenClaims exactly when the token
response actually carried one — leaving TokenSet.HasIDToken false is
a normal outcome, not an error. A deployment that only needs access
tokens can drop "openid" from a client's AllowedScopes entirely and
run this library as plain OAuth 2.0 + FAPI 2.0.
See ARCHITECTURE.md for the full design rationale and package layout, and conformance/ for how each role is tested against the OpenID Foundation conformance suite.
Full conformance and capability status (the detail behind the certification and checklist above)
All three roles (
client,server,resource), the shared internal protocol core,keys,storage(including a reusable storage contract test suite for downstream backends),extension, the hardenedfapihttptransport, client-side AS discovery (client.Discover+keys.NewJWKSIssuerKeySource) and thefapitestreal-HTTP interop harness are all implemented and covered by tests, including end-to-end authorization flows — both hand-configured and fully discovery-driven — under the FAPI 2.0 baseline and message-signing profiles. Both theserver(authorization server) andclient(relying party) roles have been run clean against the OpenID Foundation conformance suite's FAPI2 baseline and message-signing test plans, run underserver's default JWT access-token format and again under mTLS-bound access tokens (RFC 8705 §3); both roles have also been run clean againsttls_client_auth/self_signed_tls_client_authclient authentication (RFC 8705 §2) and against CIBA (OpenID Connect CIBA Core 1.0, poll and ping delivery, mTLS-bound tokens, the OIDFfapi-ciba-id1plan) — see conformance/ for the full breakdown and pass counts per plan. Rich Authorization Requests (RFC 9396) are implemented end-to-end across the PAR-fed authorization-code flow, CIBA, and the client_credentials grant (RFC 9396 §6), including a per-type narrowing hook so a resource owner can grant less than what a client requested on the first two — the OIDF suite has no dedicated RAR conformance plan, so this is validated by this repo's own unit, integration and end-to-end tests instead — see conformance/. The opaque access-token alternative is covered by unit/integration tests andcmd/conformance-as's own smoke test under both formats, not by a continuous live-suite run — see conformance/.resourcehas not been run against a dedicated OIDF plan (only indirectly, as a stand-in the AS plan's own happy-flow module calls).serveralso implements the RFC 6749 §4.4 client_credentials grant (opt-in viaConfig.ClientCredentialsGrantand a per-clientAllowsClientCredentialsGrant), run clean against all four FAPI2SP OP "Client Credentials Grant" register profiles (MTLS+MTLS, MTLS+DPoP, private key+MTLS, private key+DPoP) — see conformance/.clientimplements the matching relying-party side (RequestClientCredentialsToken), including aclient_credentials-onlyConfig(no browser flow, no CIBA); this has no OIDF RP-side plan to run against (the grant has no browser hop at all), so it's covered by unit tests and a real-HTTPfapitestround trip instead.server.Config.OAuthOnlyturns the server into a pure OAuth 2.0 + FAPI 2.0 AS — "openid" is refused as a requested scope everywhere (PAR, CIBA, client_credentials alike), no ID token is ever issued, andMetadataomits every OIDC-only field (subject_types_supported,id_token_signing_alg_values_supported) — covered by unit tests and a real-HTTPfapitestround trip, not an OIDF plan (the suite has no bare-OAuth2 FAPI2 plan to run against).The
federationpackage adds OpenID Federation 1.0 (Final) support: Trust Chain resolution (Resolver, §10, enforcing everyconstraintsclaim and a resolver-wide path-length ceiling), self-issuance of an entity's own Entity Configuration (SelfIssuer), Automatic Client Registration for an OP (§12.1,AutomaticClientRepository— including every RFC 8705 mTLS client authentication method, reading a resolved RP's own certificate straight from itsjwks/jwks_uri's ownx5cmember forself_signed_tls_client_auth), the symmetric capability on the RP side (client.DiscoverViaFederation— the sameDiscoveredMetadataclient.Discoverproduces, sourced from a Trust-Chain-verifiedopenid_providerobject instead of a live.well-known/openid-configurationfetch), acting as a Trust Anchor or Intermediate (SubordinateIssuer, §3.2), and Trust Marks end to end — verification (§7), issuance (TrustMarkIssuer), and live status queries (§8,Resolver.CheckTrustMarkStatus) — plus Trust Marked Entities Listing request validation (§9), the Resolve endpoint (§8.3,Resolver.ResolveViaEndpoint/ResolveIssuer) — both sides: querying a peer's resolve-as-a-service endpoint instead of walking its Trust Chain hop by hop, and signing a response for an embedder's own already-resolved result — and the Federation Historical Keys endpoint (§8.7,Resolver.FetchHistoricalKeys), both sides: querying a peer's retired keys (with their own expiry and, if applicable, revocation status) to keep an older Trust Chain verifiable after key rotation, and signing that response for an embedder's own retired keys. Explicit Registration (§12.2) is not implemented: an OP can accept RPs via Automatic Registration, but provisioning a distinctclient_id/client_secretthrough a dedicated federation registration request is not supported. Seefederation/doc.gofor the exact scope of every capability above.
- FAPI 2.0 Security Profile
- FAPI 2.0 Message Signing
- RFC 9126 — Pushed Authorization Requests
- RFC 9449 — Demonstrating Proof of Possession (DPoP)
- RFC 8705 — Mutual TLS Client Authentication and Certificate-Bound Access Tokens
- OpenID Connect Client-Initiated Backchannel Authentication (CIBA) Core 1.0
- RFC 9396 — Rich Authorization Requests
See CONTRIBUTING.md for the conformance-first development philosophy and pre-PR checklist, SECURITY.md to report a vulnerability, and CHANGELOG.md for release history.
MIT — see LICENSE.
OpenID®, OpenID Connect™, and OpenID Certified™ are trademarks or registered trademarks of the OpenID Foundation in the United States and other countries. Use of these marks here is limited to the certified conformance statement above, per Section 3(d) of the OpenID Certification Terms and Conditions.
