Consent screen
This is the one piece you need to host yourself: a page, on your own domain, that the third-party app's user is sent to in order to log in and approve (or deny) the connection.
Embed the widget
Paste this on the page you want to act as your consent screen, and tell the connecting app the URL of that page:
<div id="YOUR_BLOCK_REFERENCE_ID"></div>
<script type="text/javascript">
var configuration = {
referenceId: 'YOUR_BLOCK_REFERENCE_ID',
type: 'authorization',
authType: 'auth2',
theme: 'dark',
success: (data) => {
console.log('success response', data);
},
failure: (error) => {
console.log('failure reason', error);
},
};
</script>
<script
type="text/javascript"
onload="initVerification(configuration)"
src="https://36blocks.com/assets/proxy-auth/proxy-auth.js"
></script>
Replace YOUR_BLOCK_REFERENCE_ID with your Block's reference ID (the same one you already use for ordinary login and signup widgets). authType: 'auth2' is what switches this into OAuth consent mode instead of a plain login widget.
The success and failure callbacks are not used for the OAuth outcome. They're only for the plain login and signup paths this same widget also supports elsewhere. Once your user approves or denies, the widget navigates the browser directly to the connecting app's own redirect_uri. There is nothing for your page's JavaScript to handle after that point.
What the connecting app needs to send
The third-party app builds a link to your consent screen page's URL (the one with the snippet above) and sends your user's browser there with its OAuth request appended as query parameters. The widget reads these directly from the page URL, not from anything in the configuration object:
| Param | Required | Notes |
|---|---|---|
client_id |
always | From the OAuth Config you created. |
redirect_uri |
always | Must exactly match one of the URIs you registered for that config. |
response_type |
always | Must be the literal value code. |
scope |
optional | Space-separated list, for example profile email tickets:read. Omit entirely if not needed. |
code_challenge |
required for public clients (and any confidential client with Require PKCE turned on) | See PKCE, below. |
code_challenge_method |
required alongside code_challenge |
Must be exactly S256. plain is not accepted. |
state |
recommended | Opaque value of the connecting app's own choosing, echoed back unchanged on the final redirect. Standard practice for the connecting app to detect CSRF; you don't need to do anything with it yourself. |
Example link a third-party app might send your user to:
https://your-app.example.com/connect?client_id=aZ9k...&redirect_uri=https%3A%2F%2Ftheirapp.example.com%2Fcallback&response_type=code&scope=profile%20email
If any of these are missing or invalid (unknown client_id, a redirect_uri that isn't registered, and so on), the widget shows a plain error message and stops. It never guesses or redirects anywhere in that case, since the destination hasn't been verified yet.
PKCE
If PKCE is required for the config being used, the connecting app (not your widget, not your backend) is responsible for generating the PKCE pair, before it ever sends the user to your consent screen:
Generate a random
code_verifier(a high-entropy string, 43 to 128 characters per RFC 7636).Compute
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier)).Send
code_challengeandcode_challenge_method=S256as part of the link to your consent screen (table above).Hold onto the original
code_verifier. It's sent later, to the Exchange OAuth Token endpoint, to prove it's the same app that started the flow.
Your widget and your backend never see or generate code_verifier. They only ever see and check code_challenge.
What happens on your consent page
The widget validates the incoming request. On failure: a static error, nothing else happens.
On success, your user sees your normal login or signup screen. Whichever login methods you already have enabled for this Block (password, social login, OTP, and so on) all work exactly as they do anywhere else; nothing about them changes for OAuth.
Once logged in, a consent screen appears showing the connecting app's name and the scopes it requested, with Allow and Deny actions.
Approve or deny sends the browser to the connecting app's
redirect_uri:Approve:
redirect_uri?code=...&state=...Deny:
redirect_uri?error=access_denied&state=...
From here, everything happens on the connecting app's own backend, starting with the Exchange OAuth Token endpoint.