-
Notifications
You must be signed in to change notification settings - Fork 386
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
@W-16171409: [Android] Add QR Code Login Support in MSDK #2594
base: dev
Are you sure you want to change the base?
@W-16171409: [Android] Add QR Code Login Support in MSDK #2594
Conversation
For now launches QR code reader and print url to log
Using user agent flow if no pkce code verifier provided
…Style And Commentary Cleanup)
It's worth noting I did intend to include commits from the spike performed by @wmathurin. I rebased his branch on |
public override fun onSaveInstanceState(bundle: Bundle) { | ||
super.onSaveInstanceState(bundle) | ||
webviewHelper?.saveState(bundle) | ||
public override fun onSaveInstanceState(outState: Bundle) { |
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.
This was an unrelated yet low-risk inspector cleanup.
* @return Boolean true if a log in attempt is possible using the provided QR | ||
* code content, false otherwise | ||
*/ | ||
fun loginFromQrCode( |
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.
All the new methods here should look very familiar to @wmathurin. I did apply quite a bit of comment and naming thought though to reflect my own journey in understanding how it all worked plus see if I could make the semantic match through all the reference documentation. There's some Kotlin style added as well for extra credit.
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.
@JohnsonEricAtSalesforce @wmathurin Is there any kind of profile limitation to this login option? If not should we consider moving this to a standalone utility class that could be used by LoginActivity and native login consumers? Perhaps native login support is a new story to itself, just trying to be forward thinking so we don't have to deprecate and move APIs around if possible.
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 bridge url is supposed to be loaded in a web view to get the tokens or the code - it is not a headless API. So it's another form of web view based login.
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.
Yes, but despite it being a web based login it is possible to do it without the customer ever seeing a webview. You can put a button on a native login screen that has the same code as the QrCodeEnabledLoginActivity
from the template app and if the user is pre authorized (a requirement for headless flow) they don't have to accept connected app policy. This is obviously work well beyond the scope of this PR and would require a headless webview but it sounds possible, right?
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.
It's like the web view to get a code for the SP in the IDP-based login. You have to show it because user interaction might be needed.
But you are right that you could launch it from the native login screen.
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.
Yeah, if the user is preauthorized, we could hide the web view. I guess we could let the mobile app know whether to show the web view or not by adding a field in the JSON we encode in the QR URL.
* @param frontdoorBridgeUrl The UI Bridge API front door bridge API | ||
* @param pkceCodeVerifier The PKCE code verifier | ||
*/ | ||
internal fun loginWithFrontdoorBridgeUrl( |
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.
@wmathurin - I made this internal
. Was there any reason it wasn't before?
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 packing of front door bridge URL and PKCE in a QR code will be up to the apex or java page.
Hopefully it will use the attributes names we recommend, if it does not, an app could parse them out itself and call this method directly?
I guess if we make the method internal, it will force the server page to use the attributes names in the JSON that we expect.
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.
That's very helpful, since I was also starting to wonder where a custom APEX with different structure would tie in. I'll make this public again!
Tests results for SalesforceSDKGenerated by 🚫 Danger |
e0c01af
to
f9ea0e5
Compare
Hold merging this to |
@@ -661,7 +661,7 @@ open class OAuthWebviewHelper : KeyChainAliasCallback { | |||
) | |||
|
|||
else -> when { | |||
instance.useWebServerAuthentication -> onWebServerFlowComplete(params["code"]) | |||
codeVerifier?.isNotEmpty() == true -> onWebServerFlowComplete(params["code"]) |
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.
This is a bug and needs to be reverted as it will break User Agent flow login. codeVerifier
is always created no matter which flow we are using.
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.
You are right, I did not try user agent flow when doing the spike.
But we can't just revert.
With QR login, we will decide what flow to use based on what came through the JSON encoded in the QR URL.
If the JSON contains a code verifier, we use it and we should to a web server flow. And we should set a new flag saying that web server flow should be used.
That flag should be set to instance.useWebServerAuthentication by default.
We should use the new flag here.
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.
Thanks, @brandonpage (and @wmathurin)! I'll take a look.
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.
Okay. So if I understand correctly the QR URL can/should override the app's setting for useWebServerAuthentication
? Sounds like something that should be documented.
Also is User Agent Flow supported? The code above appears to require PKCE.
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.
We support both, if the QR encodes a code verifier we expect to the bridge URL to do a web server flow and the redirect to get us a code. If the QR comes with an empty/null code verifier, then the code verifier ends up not being defined and the code above will take the user agent branch. The bridge URL should do a user agent flow and the redirect get us the refresh tokens.
During the spike, I played with both, but the web server flow case meant a longer URL encoded in the QR which made it harder to read with the reader. I could not get it to work completely. See https://salesforce.quip.com/JXmvAwirhR3V#temp:C:IIO55768e89acdc49948a3be45bf
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.
@JohnsonEricAtSalesforce Before closing the story, we need to make sure user agent and web server flow work with and without QR. During the spike, I did not test them all or get them all working.
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.
@wmathurin & @brandonpage - I broke out W-16336715: [MSDK Android] Correct QR Code Log In When Using Web Server to track this in detail. I'll commit that here before we merge for 12.1 or whichever release QR code login lands in soon.
I also broke out W-16336722 to track the other bug in Quip regarding the main activity not being displayed.
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.
Where the QR Code Login work should live isn't a blocker, but the User Agent Flow issue I mentioned is.
…ing login using front door URL and code verifier to override web server Vs. user agent flow)
// Determine if presence of override parameters require the user agent flow. | ||
val overrideWithUserAgentFlow = isUsingFrontDoorBridgeUrl && frontDoorBridgeCodeVerifier == null | ||
when { | ||
instance.useWebServerAuthentication && !overrideWithUserAgentFlow -> |
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.
💤 [No after hours reply needed] @brandonpage & @wmathurin, this is my current thinking for storing the front door bridge URL and its optional accompanying code verifier as dedicated properties so we may then use them to determine the authentication flow between web server and user agent. That's for this thread from earlier:
This looks a lot like what I have in place for iOS in SFOAuthCoordinator.
Just having an outside force overriding the app's chosen auth flow is complicated, so I want to internalize that from the app and try to keep our code simple. I was hoping just storing those and then clearly determining this one local variable would keep that readable. I'm open the suggestions, though.
On the iOS side, SFOAuthCoordinator is the WKNavigationDelegate. It would possibly be a lot easier to maintain if that was a separate class chosen just when a front door URL is in place. I'm thinking "one class per job" rather than a single class with an overly complicated control flow. I didn't do that yet, but perhaps when we convert that to Swift and here we eliminate OAuthWebViewHelper we could really simplify the code for this complicated set of logic flow.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #2594 +/- ##
============================================
+ Coverage 51.41% 57.10% +5.69%
- Complexity 1789 2424 +635
============================================
Files 146 187 +41
Lines 12097 15204 +3107
Branches 1712 2135 +423
============================================
+ Hits 6220 8683 +2463
- Misses 5178 5615 +437
- Partials 699 906 +207
Flags with carried forward coverage won't be shown. Click here to find out more.
|
🎸 Ready For Review! 🥁
This adds support for log in via log in QR codes generated with the UI Bridge API to MSDK. This completes a very detailed spike previously completed by @wmathurin and directly inherits from that codebase.
Before reviewing, I highly recommend reading this document and references in detail:
👉🏻 https://salesforce.quip.com/JXmvAwirhR3V
There's actually very little if any logic change from the spike code. What I did try to apply was my novice's eye to the topic so we can name and document the code such that it'll be a bit more approachable for those uninitiated to the UI Bridge API, how that is delivered via the QR code and the many touch points that has in MSDK's log in logic. I did the same in the companion pull request that introduces commented out content to our template guiding a developer through enabling this in a new app.
The companion template update is in forcedotcom/SalesforceMobileSDK-Templates#417