Files
iOS/Sources/App/Frontend/WebView/WebViewController+ReAuth.swift
Bruno Pantaleão Gonçalves 5320df2813 Update URL port and scheme at the end of webview login (#4728)
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
In case the mdns discovery starts the onboarding and suddenly the
onboarded url gets redirected to a different port or scheme, we are not
catching that and updating the onboarded URL to match that, more
information on the upper level task.
https://github.com/home-assistant/iOS/issues/4724

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
2026-06-11 11:52:56 +02:00

88 lines
3.5 KiB
Swift

import PromiseKit
import Shared
import UIKit
extension WebViewController {
func performReauthentication(using urlType: ConnectionInfo.URLType) {
let connectionInfo = server.info.connection
guard let baseURL = connectionInfo.address(for: urlType) else {
Current.Log.error("No URL available for re-authentication with type \(urlType)")
showReauthFailureAlert(error: ServerConnectionError.noActiveURL(server.info.name))
return
}
do {
let authDetails = try OnboardingAuthDetails(baseURL: baseURL)
authDetails.exceptions = connectionInfo.securityExceptions
authDetails.clientCertificate = connectionInfo.clientCertificate
let login = OnboardingAuthLoginImpl()
firstly {
login.open(authDetails: authDetails, sender: self)
}.then { result -> Promise<(URL?, TokenInfo)> in
// The login web view may have been redirected to a different port/scheme; re-authenticate
// against the address it actually ended on, and remember it to update the stored URL.
let correctedURL = result.resolvedURL?.sameHostRedirectBaseURL(from: baseURL)
return AuthenticationAPI.fetchToken(
authorizationCode: result.code,
baseURL: correctedURL ?? baseURL,
exceptions: authDetails.exceptions,
clientCertificate: authDetails.clientCertificate
).map { (correctedURL, $0) }
}.done { [weak self] correctedURL, tokenInfo in
guard let self else { return }
applyNewToken(tokenInfo, correctedURL: correctedURL, urlType: urlType)
}.catch { [weak self] error in
guard let self else { return }
if let pmkError = error as? PMKError, pmkError.isCancelled {
Current.Log.info("Re-authentication cancelled by user")
return
}
Current.Log.error("Re-authentication failed: \(error)")
showReauthFailureAlert(error: error)
}
} catch {
Current.Log.error("Failed to create auth details for re-authentication: \(error)")
showReauthFailureAlert(error: error)
}
}
private func applyNewToken(
_ tokenInfo: TokenInfo,
correctedURL: URL? = nil,
urlType: ConnectionInfo.URLType? = nil
) {
server.update { serverInfo in
serverInfo.token = tokenInfo
if let correctedURL, let urlType {
Current.Log.info("Updating \(urlType) URL to redirected address \(correctedURL) during re-auth")
serverInfo.connection.set(address: correctedURL, for: urlType)
}
}
connectionState = .unknown
if let api = Current.api(for: server) {
api.connection.disconnect()
api.connection.connect()
}
hideEmptyState()
refresh()
Current.Log.info("Re-authentication successful, tokens updated and WebView refreshing")
}
private func showReauthFailureAlert(error: Error) {
let alert = UIAlertController(
title: L10n.Alerts.AuthRequired.title,
message: error.localizedDescription,
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: L10n.okLabel, style: .default))
present(alert, animated: true)
}
}