Web-based authentication integrations in Pugpig apps using PKCE
Table of Contents
The Pugpig platform offers several methods for users to gain access to paywalled content, these include in-app purchases of subscriptions or editions and a native sign-in UI which we can connect to the authentication system of your choosing.
We also know that in some cases customer will have built mature, powerful sign in flows of their own, and the app would be better served by handing off the authentication process to these systems. To cater for such cases, all Pugpig apps now support presenting an externally-hosted web page to conduct the authentication, and then securely passing the result to the app.
Note on flows that leave the app
In some PKCE flows (for example, passwordless logins) an email is sent to the user with a magic link or something like that. We do NOT support magic links re-opening the app at a certain point in the flow. This is because it isn't possible to reliably open an app from a browser redirect. Instead, the email should either:
- provide a code that the user can type into your flow in the app without leaving the app
- set something server side that the flow can poll for, and then continue when done (like Google tend to do)
Some example providers we've used in the past are:
- Auth0
- Piano
- Microsoft B2C
- WP OAuth WordPress Plugin (https://wp-oauth.com/)
- Custom OIDC implementations (which all support OAuth 2.0)
This document explains what information you need to give to us, and what we need to supply to you. Note that the location you get this information, or configure your provider will differ based on your providers. Please refer to their documentation on details for this.
There is also an explainer of how it all works.
What we need from you
Important: We prefer to transmit sensitive details a secure way. We use Keybase (https://keybase.io/) and our user is pugpig. However, note that by design, using PKCE, nothing below needs to be considered sensitive except maybe the test users. If you even have a client secret, then by definition you aren't using PKCE.
- Client ID - normally one client ID per platform although some providers allow one client ID with multiple callback URLs
- Auth HTML page - the HTML page that displays the login/register screen, and an optional parameter specifying if the default is login or register e.g. https://www.acme.com/login.html?state=register
- Token endpoint - the standard OAuth 2.0 endpoint : https://www.acme.com/oauth/token
- PugPig Test Users - in order to test the flows, you need to provide us a user that covers every case you wish us to test (e.g. inactive, active with some permission, active with different permissions, etc)
- Entitlement specification - The details for the entitlement logic once we have the access token - this can be very custom. Although we do not recommend it, some clients will grant access based on just the access token. See Common Pitfalls.
Note that you will still need an Authentication Pack - all the details are here: https://pugpig.zendesk.com/hc/en-us/articles/360003980897-Pugpig-Authentication-Setup-Pack
The only difference is that the sign in call will be handled using OAuth, not via an API call.
Note on Accessibility
The Pugpig Apps are designed to be accessible to as many users as possible. If you are providing a login/registration screen, please ensure it works well with screen readers.
What you need from us
You will need the callback URLs that need to be configured by you in your provider. The callback URLs are usually of the form below. If you do not know your bundle ID/package ID or vanity domain, please let us know:
Platform | Format | Example |
---|---|---|
iOS | bundle.id://authcallback/ | com.acme.app://authCallback |
Android | package.id://authcallback/ | com.acme.app://authCallback |
Web | https://webreader.vanity.root.url/ | https://reader.acme.com/ |
What is OAuth 2.0 with PKCE
Rather than devise a method of our own, our implementation utilises the OAuth 2.0 framework, specifically Proof Key for Code Exchange (PKCE hereafter). This is a security protocol specifically designed for use in mobile apps and is ideally suited to what we're trying to achieve.
Specifically, our apps will allow a user to:
- When required, open a web-page hosted at a destination of your choosing
- Securely verify the validity of the client to the authentication server
- Conduct an authorisation challenge using the user-supplied login details
- Interpret the response and subsequently give access to all, none, or a subset of the app's content.
FLOWS
There are 2 distinct ways a user can enter the PKCE flow.
Immediately after subscribing
- User purchases a subscription via In-App Purchase
- User is presented a prompt asking them to link their subscription
- User agrees to prompt and completes PKCE flow in a webview
- Subscription is now linked to account
Later after subscribing
- User purchases a subscription via In-App Purchase
- User is presented a prompt asking them to link their subscription
- User declines prompt
- User later taps "Link subscription" in the settings/account tab
- User completes PKCE flow in a webview
- Subscription is now linked to account
Receipt postback is always optional, mandating it would result in the app not being accepted to the app stores. If the user does not link their accounts they'd still retain access through their in app purchase, and they would still be able to link their subscription at any time in the future.
Because of our adherence to the PKCE protocol, Pugpig doesn't maintain a spec or implementation guide for our web-based authentication integrations, instead we'll refer you to the docs detailed below to help guide design and planning.
PKCE spec. This is the canonical source of truth that our code's expectations are based on, and should serve to detail the necessary server-side configuration: https://tools.ietf.org/html/rfc7636
OAuth 2.0 PKCE explainer. Details how PKCE fits into the OAuth framework: https://oauth.net/2/pkce
Frequently-encountered issues:
- Identity providers which do not support PKCE or through misconfiguration require a client secret. As all Pugpig apps/clients are considered "public" by RFC7636's definition, they cannot contain secrets, and therefore may only use the PKCE flow.
- Incorrect scope and/or lack of authorising API. The default openid scope is only sufficient for id_token, which is insufficient for authorising access to content. id_tokens are designed for authentication (who you are) not authorisation (what you're allowed to do). We therefore require a scope which yields an access_token which we can use to query your authorisation API.
- In order to save users from having to login every time the use the app/reader, we require a refresh_token, either using the standard "offline_access" scope or some other scope. It is also important that the TTL of the refresh token be at least double the mean duration between user sessions. E.g. If you publish monthly, users are likely to read once a month (unless they go on holiday, in which case they might miss a month etc), but they should not be logged out just for missing one publication. Worse still if the refresh tokens last less time than the mean time between publications, then users are likely to be logged out every time they return to their app/client.
- Not having a separate entitlement call - if you used Claims Based Authorisation (e.g. you do not hit anything endpoint) the granting or revoking of access with take as long as the token TTL, or might even require the user logging in again. This is not recommended!