Skip to content
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

Handle https callback url #524

Merged
merged 6 commits into from
Oct 24, 2024
Merged

Conversation

etoledom
Copy link
Contributor

@etoledom etoledom commented Oct 22, 2024

Closes #

Description

This PR is aimed to solve the problem where a oauth callback used has a https scheme.
Since WP.com OAuth only supports https, custom schemes can not be used.

Testing Steps

Pocket Casts PR for testing: Automattic/pocket-casts-ios#2267
Tests on both SDK and PocketCasts:

  • Cancel the OAuth flow before completing it.
    • See the Login required error screen.
  • Full OAuth flow:
    • Open the quick editor and complete the OAuth flow successfully
  • OAuth errors:
    • Revoque the access token (it should appear as Pocket Casts for the Pocket Casts app).
    • Open the Quick Editor after it being logged in successfully.
      • See the Token expired error.
    • Log in with a different email.
    • Open the Quick Editor. It should show the previous email on the web view.
    • Accept without changing the email.
      • See the wrong email error.

@wpmobilebot
Copy link

wpmobilebot commented Oct 22, 2024

Gravatar UIKit Prototype Build📲 You can test the changes from this Pull Request in Gravatar UIKit Prototype Build by scanning the QR code below to install the corresponding build.
App NameGravatar UIKit Prototype Build Gravatar UIKit Prototype Build
Build Number1594
Version1.0
Bundle IDcom.automattic.gravatar-sdk-demo-uikit.prototype-build
Commit6c24b1f
App Center BuildGravatar SDK Demo - UIKit #308
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@wpmobilebot
Copy link

wpmobilebot commented Oct 22, 2024

Gravatar SwiftUI Prototype Build📲 You can test the changes from this Pull Request in Gravatar SwiftUI Prototype Build by scanning the QR code below to install the corresponding build.
App NameGravatar SwiftUI Prototype Build Gravatar SwiftUI Prototype Build
Build Number1594
Version1.0
Bundle IDcom.automattic.gravatar-sdk-demo-swiftui.prototype-build
Commit6c24b1f
App Center BuildGravatar SDK Demo - SwiftUI #307
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@etoledom etoledom self-assigned this Oct 22, 2024
@etoledom etoledom added this to the Milestone 4 - Quick Editor milestone Oct 22, 2024
@etoledom etoledom marked this pull request as ready for review October 22, 2024 13:17
func onAuthenticationFinished() {
if let fetchedToken = oauthSession.sessionToken(with: email)?.token {
self.fetchedToken = fetchedToken
oauthError = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WhenoauthSession.hasValidSession(with: email) returns false (in performAuthentication()), then oauthSession.sessionToken(with: email)?.token will return nil, and vice versa.

❓ Since we're already setting oauthEerrorl in performAuthentication() in cases when oauthSession.hasValidSesions(with: email) is false, does it makes sense to move this oauthError = nil there also when it's true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem here, is that when the https flow is triggered (which will potentially be all the cases on production), the performAuthentication() function won't be canceled (to close the web view), and the flow is finished through the notifications, which will call onAuthenticationFinished(), also in the case of success. And in this case we might need oauthError = nil inside onAuthenticationFinished().

Maybe what you described will handle all cases properly, but I'd be extra careful testing every success and error case (also a success after an error screen), if there's any change here.

Comment on lines 90 to 91
NotificationCenter.default.post(name: .authorizationError, object: error)
await shared.authenticationSession.cancel()
Copy link
Contributor

@andrewdmontgomery andrewdmontgomery Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Is it ok to send the notification before calling await ....cancel()

Could it be problematic for a recipient to receive that notification before await shared.authenticationSession.cancel() returns?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it could be problematic, but it does seem safer to make this change 👍

Copy link
Contributor

@andrewdmontgomery andrewdmontgomery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works as described now! Looks good. I left a couple of questions. But I wouldn't let them hold this up.

overrideToken(newToken, for: email)
return newToken
shared.overrideToken(newToken, for: email)
await shared.authenticationSession.cancel()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Just wondering why the manual cancel() is necessary? Doesn't the oauth session end itself once it's successful?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the callback URL comes from universal links, the oauth session never returns, so it's never a "success", and the OAuth web view won't dismiss.

As every real scenario will use https and universal link, it will always need this manual cancelling, so I think it safer to call it always, though is not necessary for our particular case of the demo app with the custom scheme exclusion.

Testing the demo app, it didn't seem to be a problem, so I decided to keep the logic simple.

Copy link
Contributor Author

@etoledom etoledom Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the canceling, the web view stays like this without dismissing:

So the canceling is basically the simplest way I found to dismiss it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, interesting. Thanks!

Copy link
Contributor

@pinarol pinarol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@etoledom etoledom merged commit c439d43 into release/3.0.0 Oct 24, 2024
9 checks passed
@etoledom etoledom deleted the etoledom/handle-https-callback-url branch October 24, 2024 07:36
@pinarol pinarol added the enhance New feature or request label Oct 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhance New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants