And Why Is It Mandatory for Securing Public Clients Using Openid Connect

Published
Length
3 min read

Luis Felipe Dias

All posts

You protect login flows by adding Proof Key for Code Exchange to every request. Understanding what PKCE does and why is it mandatory for securing public clients using OpenID Connect stops code theft. Teams often start by setting up basic login redirects for mobile or browser apps. Without extra checks, attackers can steal the login code and use broad role permissions. What PKCE does and why is it mandatory for securing public clients using OpenID Connect Public apps run on user devices like p

Mandatory Access Control (MAC) + OpenID Connect (OIDC): the complete guide

Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.

Free white paper. No spam. Unsubscribe anytime.

You protect login flows by adding Proof Key for Code Exchange to every request. Understanding what PKCE does and why is it mandatory for securing public clients using OpenID Connect stops code theft. Teams often start by setting up basic login redirects for mobile or browser apps. Without extra checks, attackers can steal the login code and use broad role permissions.

What PKCE does and why is it mandatory for securing public clients using OpenID Connect

Public apps run on user devices like phones or web browsers. These apps cannot keep a static secret safe from curious users or attackers. Anyone can inspect the app code and read hidden keys.

In a standard login flow, the identity server sends back a temporary code. The app trades this temporary code for a session token. On a phone or browser, a bad app can intercept that temporary code.

PKCE fixes this gap by creating a one-time secret for every single login attempt. Before the user logs in, the app makes up a random string. This random string is the verifier.

Next, the app hashes the verifier to create a challenge string. The app sends this challenge string to the identity server when starting the login. The identity server saves the challenge and shows the login page to the user.

After the user logs in, the server sends back the temporary code. Now the app asks for the final token and sends the raw verifier string. The identity server hashes the verifier and checks if it matches the saved challenge.

If a bad app steals the temporary code, it still lacks the original verifier. Without the verifier, the attacker cannot trade the code for a working token. This step binds the login code to the exact app instance that started it.

How to set up the flow and what gaps remain

To set this up, your team registers the mobile or browser app as public. You disable static client secrets in your identity server settings. Then you require the hash challenge method for every login request on that app.

Mandatory Access Control (MAC) + OpenID Connect (OIDC): architecture patterns and best practices

Continue reading? Get the full guide.

Free. No spam. Unsubscribe anytime.

Your app code generates a fresh random string each time a user clicks login. It stores this string in temporary memory until the redirect comes back. Then the app sends the string to finish the token trade.

This native setup solves the problem of stolen login codes during the redirect step. It proves that the same app started and finished the login flow. It also removes the bad habit of shipping static secrets inside browser bundles.

Still, this login check only decides who gets a session token at the start. Once the app holds a valid token, the identity server steps out of the way. The login flow cannot see what queries or commands run during the active session.

If a user role has broad permissions, every request carries that full power. A valid token lets the user or app run wide data reads or writes. The login check cannot block risky commands or rewrite sensitive fields like emails in flight.

Teams also lack a central log of individual actions taken after the login finishes. You know who logged in, but you do not see what data they touched. Securing the token exchange is only the first step in protecting your systems.

Govern statements and responses across databases and APIs

Good config and scoped roles are needed setup. They do not check single queries in flight or mask sensitive fields in returned rows. Across Postgres, MySQL, SQL Server, MongoDB, ClickHouse, Kubernetes APIs, SSH, and internal HTTP endpoints, hoop.dev sits inline in the protocol beside each supported service as an open-source proxy, a sidecar for your database or API. For every query or command an AI agent or engineer runs against production, hoop.dev decides to pass, mask, block, or hold it for human approval.

First, hoop.dev guardrails block banned queries before they run or hold risky ones for review, and hoop.dev data masking rewrites matched sensitive values in responses in memory. Furthermore, hoop.dev holds SOC 2 Type II and is open source on GitHub.

Frequently asked questions

What makes an app a public client in OpenID Connect?

A public client is any app that runs on a device you do not control. Native mobile apps, desktop tools, and single-page browser apps are all public clients. They cannot hide static passwords or keys because users can inspect the local files.

Why can we not use a plain text challenge during the login check?

If you send a plain text challenge, an attacker on the network can read it. The attacker can then reuse that same string to claim the final token. Hashing the string ensures that watching the first request does not reveal the secret.

Does PKCE replace the need for client secrets on backend servers?

No, backend servers that live in a safe data center should still use secrets. You should use PKCE alongside client secrets on backend apps for extra safety. It protects both public apps and private servers from code injection attacks.

Save the open-source gateway.

hoop is MIT-licensed infrastructure for controlling how AI agents reach production data. Star hoophq/hoop so you can inspect it, deploy it, or share it when your team starts governing agent access.