-
Notifications
You must be signed in to change notification settings - Fork 254
feat: Add authorizeWithRequestUri method for PAR-based authentication
#1038
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for PAR (Pushed Authorization Request) flows in the SDK, enabling Backend-For-Frontend (BFF) authentication patterns. The new startForCode(requestURI:) method returns only the authorization code instead of performing token exchange, allowing backends to handle the secure token exchange using their client secret.
Key changes:
- Introduces new
startForCode(requestURI:)API with callback, async/await, and Combine variants - Returns
AuthorizationCodestruct containing the code and optional state parameter - Implements
PARCodeTransactionto handle the authorization flow without token exchange
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Auth0/WebAuth.swift | Added protocol definitions for startForCode(requestURI:) methods with comprehensive documentation |
| Auth0/Auth0WebAuth.swift | Implemented startForCode methods and PAR-specific authorize URL builder |
| Auth0/AuthorizationCode.swift | New public struct to encapsulate authorization code and state from PAR callbacks |
| Auth0/PARCodeTransaction.swift | New transaction handler for PAR code flows, similar to LoginTransaction but returns codes instead of credentials |
| Auth0Tests/PARCodeTransactionSpec.swift | Comprehensive test coverage for PARCodeTransaction including success, error, and cancellation scenarios |
| EXAMPLES.md | Added PAR usage documentation with examples for callback, async/await, and Combine patterns |
| Auth0.xcodeproj/project.pbxproj | Updated project file to include new source files in build targets |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
startForCode method for PAR-based authenticationauthorizeWithRequestUri method for PAR-based authentication
| } | ||
|
|
||
| private func buildPARAuthorizeURL(requestURI: String) -> URL { | ||
| guard let authorize = self.overrideAuthorizeURL ?? URL(string: "authorize", relativeTo: self.url), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming can be authorizeURL
| // Step 4: Send code to BFF to exchange for tokens | ||
| let credentials = try await yourBffClient.exchangeCode(authorizationCode.code) | ||
| credentialsManager.store(credentials: credentials) | ||
| } catch let error as WebAuthError where error.isUserCancelled { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error handling can be kept uniform across async await and combine example
| let provider = self.provider ?? WebAuthentication.asProvider(redirectURL: redirectURL, | ||
| ephemeralSession: ephemeralSession, | ||
| headers: headers) | ||
| let userAgent = provider(authorizeURL) { [storage, barrier, onCloseCallback] result in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets update this to use weak self and refer to storage and barrier via self inside the closure. Capturing them strongly poses a risk of memory leaks. I’ve noticed that in some of the existing code we are capturing these strongly, so it would be great to do refactoring there too
|
|
||
| private(set) var userAgent: WebAuthUserAgent? | ||
|
|
||
| let redirectURL: URL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: all of these data members could be private if they aint being called internally from other structs/classes.
|
|
||
| let authorizeURL = self.buildPARAuthorizeURL(requestURI: requestURI) | ||
|
|
||
| let provider = self.provider ?? WebAuthentication.asProvider(redirectURL: redirectURL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The provider property can take headers as parameters. Are those header values something that we need to pass to the authorize end point ?
| } | ||
|
|
||
| private func handleCallback(url: URL) -> Bool { | ||
| guard url.absoluteString.lowercased().hasPrefix(self.redirectURL.absoluteString.lowercased()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: lets avoid lowercased() for the full uri here it would create false positives for this validation. we could have lowercased() for scheme and domain
| if let fragment = components.fragment { | ||
| let fragmentItems = fragment.split(separator: "&").compactMap { pair -> (String, String)? in | ||
| let parts = pair.split(separator: "=", maxSplits: 1) | ||
| guard parts.count == 2 else { return nil } | ||
| return (String(parts[0]), String(parts[1])) | ||
| } | ||
| fragmentItems.forEach { items[$0.0] = $0.1 } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could not find the usage of fragments in subsequent code flow. if we do need fragment parsing we can put a fragment parser in utility or else please remove this
sanchitmehta94
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanchitmehta94
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanchitmehta94
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adds
authorizeWithRequestUri(requestURI:)method toWebAuthprotocol for PAR (Pushed Authorization Request) flows that return the authorization code instead of credentials.New API