Medplum OAuth Demo with SwiftUI
This guide provides instructions on setting up OAuth authentication in a native SwiftUI iOS application to authenticate with Medplum. OAuth is a widely adopted open standard that enables secure access delegation. It allows third-party applications to request access to a user’s resources, such as their account information, data, or files, without needing to obtain and store the user’s credentials (e.g., username and password).
OAuth provides a token representing the user’s consent to grant specific access rights to the requesting application. The application can use this token to perform actions on behalf of the user, such as accessing a protected API or retrieving user data, without compromising the user’s security.
In this guide, we’ll explore how to leverage OAuth with Medplum using SwiftUI and the ASWebAuthenticationSession framework. This will allow you to authenticate users and securely access their Medplum data within your iOS application.
Medplum OAuth Flow
The following link provides details of the OAuth 2.0 authorization code flow for Medplum.
AuthViewModel Class
All of the OAuth implementation is in the AuthViewModel
class. This class manages the authentication state, handles the OAuth flow, and provides methods for logging in and out.
Key Properties
isAuthenticated
: A boolean indicating whether the user is currently authenticated.accessToken
: Stores the access token received after successful authentication.error
: Stores any error messages that occur during the authentication process.clientId
: The client ID for the Medplum application.redirectUri
: The URI to which Medplum will redirect after authentication.codeVerifier
andcodeChallenge
: Used for the PKCE extension of OAuth 2.0.
Login Function
The login()
function initiates the OAuth flow, it generates a code verifier and challenge for PKCE, constructs the authorization URL with necessary parameters,and starts an ASWebAuthenticationSession
for secure, in-app authentication.
OAuth Authentication using ASWebAuthenticationSession
ASWebAuthenticationSession is an Apple-provided class in the AuthenticationServices Framework that manages web-based authentication sessions. It’s useful for OAuth flows because it; provides a secure, in-app web view for user authentication, handles callback URLs automatically, and ensures privacy using isolated sessions.
The ASWebAuthenticationSession initializer requires an authURL
and schema
.
Generating authURL and scheme (redirectUri)
Creating the authURL is straightforward using the Medplum documentation. Important: When calling the authorize endpoint with grant_type
set to authorization_code
, is to include the code_challenge
and code_challenge_method
. These parameters are required for PKCE (Proof Key for Code Exchange) and necessary for requesting the token later.
Create the code challange for PKCE
The generateCodeVerifier()
function creates and stores the codeVerifier
and codeChallenge
required for OAuth 2.0 PKCE, which enhances security for public clients like mobile apps that can’t securely store a client secret. This flow ensures robust and secure authentication, protecting user credentials and access tokens.
Create the authURL
With the code_challenge
and code_verifier
, create the authURL. The authURL is the URL to which the user will be redirected to for authentication. It includes the client ID, response type, redirect URI, scope, and code
challenge details. The loadClientId()
reads the clientId from the Secrets.plist, create this file (Property List) in Xcode.
Note: Create a Client Appliation in Medplum for the clientId and also to configure the Redirect URI (medplum-oauth://redirect
) described next.
Create the scheme URI
The scheme
is a custom URL that the app registers in its Info.plist file. It returns the authorization code to the app after the user completes the authentication process. Add the redirect URL in the Project –>
Info –> URL Types section in Xcode or manually.
Extract the scheme from the redirect URL
Create URL required by ASWebAuthenticationSession
Apple documentation for ASWebAuthenticationSession Initializer.
Create ASWebAuthenticationSession and handle the callback
Creates an ASWebAuthenticationSession with the authorization URL and callback scheme. When the user completes the authentication, the system captures the callback URL and returns it to the app, and extract the authorization code. Once the authorization code is returned, exchange it for an access token with a simple POST call to the Medplum token endpoint.
Exchanging the Code for a Token
Receive the authorization code via the handleCallback()
function in the startAuthSession, then the exchangeCodeForToken()
function obtains the access token.
The exchangeCodeForToken()
function sends a POST request to Medplum’s token endpoint with the necessary parameters, including the authorization code
and code_verifier
. Upon successful response, it updates the accessToken
and isAuthenticated
properties.
Conclusion
This AuthViewModel robustly implements OAuth 2.0 authentication with PKCE for Medplum. By using ASWebAuthenticationSession, it ensures a secure authentication flow within a SwiftUI app. Remember to handle the authentication state in the UI, displaying login options when isAuthenticated is false and secured content when it’s true.
For a complete implementation, create SwiftUI views that utilize this view model and respond to changes in the authentication state. Always following best practices for securing tokens and handling user data in production applications. Complete source code for this implementation is available on GitHub