openid / openid/AppAuth-iOS

AppAuth remembers too much between authorizationFlows / universal link not processed

Open
#562 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Objective-C
Stars
2k
Forks
867
Avg merge
4d 48m
Merged PRs (30d)
1

Description

Describe the bug
On iOS 13.5 with the latest AppAuth (1.4.0), I have a weird caching / universal link issue with logging in through AppAuth, logging out and logging back in again. AppAuth or ASWebAuthenticationSession seems to cache the universal link URL containing the code between two login attempts in the same app launch, even though I throw away the authState and currentAuthorizationFlow.

To Reproduce
Based on the documentation, I first discover the configuration from the server with AppAuth:

OIDAuthorizationService.discoverConfiguration(forIssuer: URL(string: "https://identityserver.example.com/")!) { ... }

Then, I build a new request:

let signinRedirectURL = URL(string: "https://portal.example.com/signin-oidc-ios")!
let request = OIDAuthorizationRequest(configuration: config,
                                      clientId: "ios-app",
                                      scopes: ["api"],
                                      redirectURL: signinRedirectURL,
                                      responseType: OIDResponseTypeCode,
                                      additionalParameters: nil)

and present it:

appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: viewController) { authState, error in self.processAuthState(authState, error) }

After logging in through the in-app browser popup, the universal link is processed:

if let authorizationFlow = appDelegate.currentAuthorizationFlow, authorizationFlow.resumeExternalUserAgentFlow(with: url) {
	appDelegate.currentAuthorizationFlow = nil
} else {
	print("...")
}

Finally I process the received authState:

func processAuthState(authState: OIDAuthState, error: Error) {
	if let authState = authState, let token = authState.lastTokenResponse?.accessToken {
		appDelegate.authState = authState
		self.accessToken = token // stored later on for usage by REST API
	} else {
		print("Authorization error: \(error?.localizedDescription ?? "Unknown error")")
	}
}

When logging out, I simply throw away the authState and currentAuthorizationFlow. Then, to log in again, the same process begins again.

The weird thing now is that AppAuth does not present a login in-app-browser popup with the login mask at https://identityserver.example.com/ as before in the first login attempt after each app launch, but instead it presents that same popup with the universal link like https://portal.example.com/signin-oidc-ios?code=abcdef&scope=api&state=xyz which was previously caught by iOS and forwarded to the app leading to the call to authorizationFlow.resumeExternalUserAgentFlow(with: url) from above.
Because we have not implemented the universal link fully yet, it leads to an error message, because the URL with the link is not supposed to be called in the browser at the moment but only to communicate the token to the app through the universal link mechanism.

Why does AppAuth or ASWebAuthenticationSession seemingly cache the last URL with an old token from the previous login attempt within the same app launch even though I throw away both the authState and currentAuthorizationFlow and create new ones? Is there something else I should do to "log out", clear the cookies etc?

Expected behavior
AppAuth should always present the issuer URL whenever I create a new currentAuthorizationFlow. It should not remember anything from a previous login attempt in the same "session" after app launch, e.g. when the user logs in, then logs out and logs in again without the app being relaunched.

Smartphone (please complete the following information):

  • Device: iPhone 11 / Simulator
  • OS: 13.5
  • Browser: Safari

Additional context
Using IdentityServer 4 as the backend implementation of OpenID / OAuth.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the second-login behavior around OIDAuthState.authState(byPresenting:presenting:) and resumeExternalUserAgentFlow(with:), then inspect how AppAuth-iOS and ASWebAuthenticationSession handle successive flows. Done means identifying whether the old universal-link URL is retained by AppAuth or the system session and documenting or correcting the behavior so a new flow presents the issuer URL.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, swift
Domain
authentication, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.