Written by Technical Team | Last updated 09.09.2025 | 17 minute read
For patient-facing applications in England, NHS login is the front door to identity and authentication. It gives citizens a consistent way to sign in to digital health services, while giving service providers a reliable, standards-based identity token. Technically, NHS login is an OpenID Connect (OIDC) identity provider built on top of OAuth 2.0. OIDC adds an identity layer to OAuth, so your service can prove “who the user is” at a defined level of assurance, not just obtain consented access to their resources. In practice, that means your app receives an ID token that encapsulates claims about the user (for example, name and date of birth) and, where permitted, access to an NHS number and other attributes. Those claims are cryptographically signed, so you can verify their provenance.
It’s also important to understand that many user-restricted NHS APIs don’t talk directly to NHS login. Instead, they follow a “separate authentication and authorisation” pattern. Your application authenticates the patient with NHS login and obtains an ID token; you then exchange that ID token for an access token from an NHS API authorisation server that sits in front of the API you want to call. This pattern avoids coupling every API to the citizen identity system, allows for fine-grained scopes per API, and enables additional policy enforcement (rate limiting, auditing, and consent checks) at the API gateway layer. Once you have an access token from the API’s authorisation server, you call the API with a standard Authorization: Bearer <token> header.
NHS login is for citizens. Staff authentication typically uses Care Identity Service 2 (CIS2) and smartcards or other workforce credentials. If you’re building a product that has both citizen and staff journeys, resist the urge to blend them: the policy, data minimisation rules, and technical flows differ. A patient viewing their own GP record is a different legal and technical proposition from a clinician viewing a patient’s record for direct care. Getting these personas and flows separated keeps your solution compliant and reduces rework when you get to assurance.
Finally, think of OIDC as a contract. You are agreeing to follow the standard authorisation code flow (nearly always with PKCE for native and browser-based clients), to validate tokens properly, to request only the minimum scopes you need, and to handle consent and sign-out predictably. If you treat the flow as boilerplate to be “made to work” rather than a security protocol to be implemented precisely, you will run into intermittent bugs, hard-to-diagnose errors in production, and issues during formal onboarding and assurance.
Before any code is written, line up the governance. Most NHS APIs require a set of artefacts that demonstrate information governance and clinical safety. Expect to complete a DPIA (Data Protection Impact Assessment), a clinical safety case (for example, following DCB0129/0160 where applicable), and security documentation covering secrets management, secure development, and vulnerability management. Where your product falls under a formal supplier assurance pathway, you may be asked to complete SCAL or related processes and to evidence penetration testing. Although these documents can feel separate from your build, decisions you make in architecture—like where to store refresh tokens or how you segregate environments—will feed straight into your assurance case, so bring your clinical safety officer and information governance lead into early design sessions.
On the platform side, you’ll need an account on the relevant API platform or gateway and a registered client application for each environment (sandbox, integration, pre-prod, live). Registration establishes your client identifier, allowed redirect URIs, and the set of scopes you may request. Configure an explicit allow-list of redirect URIs and treat these as immutable, version-controlled configuration. You’ll also be issued credentials for the API authorisation server (these may be separate from NHS login credentials if you are using the separate auth/authorise pattern). Keep secrets out of code; prefer a managed secret store and short rotation windows.
Your test strategy should include a plan for sandpit and mock identity journeys, where you can simulate the identity flow without touching live demographics or clinical data. Sandpit environments typically provide synthetic users, static one-time passwords for multi-factor steps, and known ID token payloads. They are designed to let you build the identity plumbing, not to validate clinical scenarios end-to-end. For that you’ll move to integration environments that replicate the authorisation flow against synthetic datasets for target APIs such as GP Connect. Expect differences between sandpit and integration; for example, sandpit may not be connected to the Personal Demographics Service (PDS), so identity-to-record matching behaves differently from live.
To keep your project on track, anchor your plan around an explicit “minimum viable integration.” That means: a working OIDC authorisation code flow with PKCE, verification of the ID token, a successful token exchange with the API authorisation server, and one end-to-end call to a representative user-restricted API using a bearer access token. Once that slice is working, you can layer in scope refinement, richer consent UX, refresh-token lifecycles, and the operational guardrails that make the service robust in production.
At the heart of the integration is the OIDC authorisation code flow. Your front end redirects the user to NHS login’s /authorize endpoint with the usual parameters: response type code, client ID, redirect URI, state, and PKCE parameters (code_challenge and code_challenge_method). You will also request scopes, starting with openid as mandatory. Additional scopes determine what claims you may receive in the ID token or from the userinfo endpoint. Some claims are mutually exclusive; others require explicit approval and justification during onboarding. Always request the minimum set of scopes that will let you render the intended experience, and design your UX to degrade gracefully if a particular claim is absent.
After the citizen completes the NHS login journey, the user agent is redirected to your redirect URI with an authorisation code and your original state value. Your back end exchanges that code at NHS login’s token endpoint for an ID token (a signed JWT) and, depending on your client type, possibly a refresh token. You must validate the ID token: verify its signature against the JSON Web Key Set, check the issuer, audience, issue time, expiration, and nonce. This step is not optional. Treat token validation as a first-class security control, wrap it in high-quality telemetry, and test failure cases (expired tokens, wrong audience, invalid signature). Only once the ID token is verified should you trust any claim values within it.
If the API you want to call adopts the separate authentication and authorisation pattern, you now present this validated ID token to the NHS API’s authorisation server. That server issues you an access token representing the combination of: an authenticated citizen identity, the scopes your client is permitted to request, and any additional policy rules (for example, consent or time-of-day restrictions). You then call the target API with that access token. From your perspective, the dance is: NHS login for identity, NHS API gateway for authorisation, and then the API for data. It’s conceptually straightforward, but getting the details right—especially around validation and error handling—makes all the difference to reliability.
Design from the outside in: what does the citizen see immediately after they return from NHS login? If you need to greet the user personally, the given_name and family_name claims might be available depending on the scopes you requested. If you need to display or link records, you may rely on the NHS number only where your use case and assurance allow; even then, you often should not display that number to the user. If your UX assumes a specific claim is always present, you are setting yourself up for brittle behaviour and support tickets. Build for variability and absence: show a neutral greeting if names are not provided; allow a manual record-linking journey if claims don’t suffice to match records in your system.
Scopes are your contract with the API and with the citizen. You request them, the citizen consents to them, and the API gateway enforces them. Aim for a narrow set of scopes that align clearly with your features. When you’re unsure whether a new scope is justified, treat it as a product question: what exact user benefit does this unlock? That clarity will help during onboarding and future audits. Remember also that some APIs introduce their own resource-specific scopes during the token exchange step; design your token acquisition abstraction to support asking for additional scopes from the API authorisation server separately from the initial NHS login scopes.
Token handling deserves careful engineering. For browser-based apps, prefer the authorisation code flow with PKCE, and avoid implicit flows. Do not store ID or access tokens in local storage where they can be exfiltrated by XSS; keep tokens in secure HTTP-only cookies with appropriate SameSite settings. On the server side, where you do have to persist tokens temporarily, enforce short lifetimes and automatic rotation. Refresh tokens recover sessions without forcing the user to reauthenticate, but they are high-value secrets. Keep them out of front ends entirely, bind them to the client, and store them only where an incident response plan can realistically cover compromise (for example, in a database protected by encryption at rest and strict access controls). Build revocation and replay-attack detection into your token service and operational dashboards.
Once you have the access token from the API authorisation server, calling a user-restricted NHS API looks like any other standards-based REST call. For example, read-only access to a patient’s GP record via a FHIR-based interface typically requires an Accept header with the correct media type, FHIR query parameters for filters and date ranges, and the bearer token in the Authorization header. Anticipate errors that indicate policy failures rather than technical faults. A 401 might mean your token expired or was issued to the wrong audience; a 403 might indicate a consent model problem or a scope mismatch. Capture correlation IDs from responses, propagate them through your logs, and surface them in your support tooling to accelerate triage with platform teams.
Error handling, retries, and idempotency matter because upstream systems in health are complex and federated. A transient 502 might be a gateway retryable condition; an OperationOutcome payload might describe a FHIR-level contractual issue that your product can correct without human intervention. Build a taxonomy of errors during integration testing and classify which ones are safe to retry, which require a new token, and which demand user action. Doing so prevents you from masking genuine defects with endless retries and from frustrating users with unnecessary “please sign in again” loops.
Data minimisation and privacy by design are not only legal obligations; they simplify your software. Many implementations are tempted to cache decoded claims in application databases. Resist that unless you genuinely need long-lived storage for a user-centric feature. Where possible, process claims in memory, derive the minimal state your application needs, and discard the rest. For example, if you simply need to know that the user is over 16 to show certain features, don’t store the full date of birth—store a boolean flag calculated at session time. Your DPIA will be easier, and your breach surface smaller.
When you integrate multiple APIs that each rely on the separate authentication and authorisation pattern, you may need to perform multiple token exchanges, one per API authorisation server. Architect a token broker component in your back end to encapsulate this complexity. It takes a validated citizen ID token and returns API-specific access tokens with the right scopes, handling caching, rotation, and error translation for the rest of your application. This not only reduces duplication; it also creates a natural choke-point for observability and policy enforcement.
Finally, plan for sign-out, both local and upstream. Offer a clear sign-out action that clears your sessions and tokens; where supported, trigger single logout with NHS login so that a user signing out of your service is not left signed in at the identity provider. Conversely, consider how you will handle upstream session expiry while your front end still holds UI state; silent reauthentication patterns must be approached carefully to avoid surprising users or creating click-jacking risks.
Security reviews and clinical safety casework can feel like a hurdle at the end of development, but they go more smoothly when you build with them from day one. Start by putting threat modelling on a cadence: review the OIDC flow, token storage, API calls, and logout journey, and identify where an attacker could intercept, replay, or forge data. Map those threats to concrete controls: strict redirect URI allow-listing, PKCE enforcement, JWK pinning, signature verification, short-lived tokens, and secure cookie flags. Back every control with an observable signal. If your token validation library rejects a JWT because the issuer is wrong or the signature is invalid, you should see a high-fidelity metric and an alert tied to a runbook.
Secrets management and key rotation are frequent stumbling blocks. Client secrets and private keys will need rotation that fits with change control windows in your host organisation. Automate the path: use a managed key vault, store only references in your configuration, and build your services to reload credentials without restarts. For asymmetric keys, establish a JWKS rollover plan and rehearse it in lower environments. The first time you discover that your JWT validation cache is holding onto an old signing key should not be during a live incident. Document the rotation cadence and ownership so your operations team can execute without contacting a developer at 2 a.m.
Clinical safety hinges on predictability and transparency. If your service shows a slice of a GP record, it should always be clear to the user what data they are seeing, how fresh it is, and whether it is a complete view. When an upstream API is unavailable, do not silently serve stale data in a way that could influence a clinical decision. Consider a “safer failure” mode that hides sensitive modules and explains the situation in plain language. Tie that to operational dashboards that show API availability, token error rates, and user journey completion—not just infrastructure metrics. Your clinical safety officer will thank you when building the hazard log and residual risk arguments.
Performance and user experience are part of safety and trust. Token exchanges add hops, and FHIR queries can be chatty. Cache responsibly: keep access tokens in memory for their short lifetime; cache stable reference data; and use conditional requests where APIs support ETags or If-Modified-Since. For citizen-facing journeys, front-load expensive calls while the identity journey is completing (for example, preparing configuration or reference data that doesn’t depend on the ID token) so the first meaningful paint feels snappy. Measure the full path from redirect to first data on screen; shave milliseconds from DNS, TLS, and HTTP/2 settings before reaching for architectural complexity.
Observability and support models should be in place before go-live. You’ll want structured logs for every identity and authorisation step, but be meticulous about not logging personally identifiable information or token contents. Instead, log token references (hashes), correlation IDs, and policy decisions (for example, “scope insufficient for endpoint /X”). Build dashboards that distinguish platform errors from your own. When a gateway returns 403 for a feature that previously worked, your support staff should be able to see at a glance whether a scope change was rolled out, a consent policy changed, or whether your recent deployment introduced a regression.
Successful teams treat the integration like a product in its own right, not an afterthought. Begin with a thin vertical slice, ideally a single feature that demonstrates clear user value—such as “View my repeat medications”—and wire it end to end using the correct OIDC flow, token exchange, and API call. In doing so, ensure you request only the scopes needed to render that screen. Document the mapping from feature to scope: it will become the backbone of your privacy notices, onboarding submissions, and support runbooks. Keep this slice deployed to an environment where non-engineers can exercise it; feedback from clinical and policy stakeholders early is far cheaper than refactors late.
Next, encapsulate identity and authorisation behind a clear interface in your codebase. Whether you’re on .NET, Node.js, Java or another stack, wrap OIDC and token exchange concerns inside a small library or service that exposes four or five high-level operations: “start login,” “handle callback,” “get user claims,” “get API token for resource X,” and “logout.” Doing this early pays dividends when you integrate additional APIs or adjust to policy changes. It also makes it easier to write deterministic tests and to swap libraries if you discover incompatibilities in lower environments.
With the core flow stable, invest in failure-first testing. Deliberately break each step in a controlled environment and verify your system fails safely and explains itself to users. Poison the nonce, tamper with the state, present an expired ID token, or switch the audience and issuer. Make sure those failures are reflected in logs and metrics. Then move up a layer: simulate API gateway throttling, consent changes, and momentary outages. A morning spent doing this will harden your implementation far more than a week of sunny-day test cases.
As you add features, resist scope creep—literally and figuratively. Each new claim or scope increases the blast radius for privacy and the likelihood of onboarding friction. Ground every request in a concrete user story and a measurable outcome. If you think you need a claim that reveals sensitive attributes, explore whether you can instead query the API for a derived fact after authorisation, or compute the minimal attribute in your own domain from existing signals. Your DPIA and security team will be far more comfortable approving “over-16” than storing a full date of birth unnecessarily.
Finally, plan your go-live as a phased exercise. Start with a constrained rollout: a small geography, a subset of GP practices, or a limited feature set. Watch your metrics and support channels. If you see a pattern of errors around token exchange or specific endpoints, pivot to improving error messages and retriable behaviour before scaling up. Keep a tight feedback loop with the platform and API teams; file clear, reproducible issues with timestamps, correlation IDs, and token reference hashes. A collaborative posture here accelerates fixes and helps everyone improve the shared platform.
Implementing an NHS API integration with NHS login and OAuth 2.0 is fundamentally about respecting contracts: the OIDC protocol contract that governs how you authenticate users and validate tokens; the authorisation contract that binds scopes, consent, and policy to specific APIs; and the social contract with citizens that you will request only what you need, safeguard their data, and fail safely. Teams that internalise those contracts ship faster, onboard more smoothly, and earn trust.
If you embrace the separation of concerns—NHS login for identity, an API gateway for authorisation, and clear boundaries in your own code—you’ll find the technical path quite orthodox. The hard part is the craft: asking for the minimum scopes, validating diligently, planning rotations and rollouts, and designing failure states with the same care you give to happy paths. Do those well, and your product will not only pass assurance, it will feel reliable and respectful to the citizens it serves.
Is your team looking for help with NHS API integration? Click the button below.
Get in touch