Files
iOS/Sources/App/Frontend/WebView/WebViewController+ReAuth.swift
Bruno Pantaleão Gonçalves 114c73854d Add WebView re-authentication flow (#4513)
<!-- 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 -->

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="2792" height="1558" alt="CleanShot 2026-04-14 at 15 20
18@2x"
src="https://github.com/user-attachments/assets/59c1e658-d7fd-4b9c-9712-9421911ce554"
/>

## 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-04-14 13:35:29 +00:00

77 lines
2.7 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 { code -> Promise<TokenInfo> in
AuthenticationAPI.fetchToken(
authorizationCode: code,
baseURL: baseURL,
exceptions: authDetails.exceptions,
clientCertificate: authDetails.clientCertificate
)
}.done { [weak self] tokenInfo in
guard let self else { return }
applyNewToken(tokenInfo)
}.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) {
server.update { serverInfo in
serverInfo.token = tokenInfo
}
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)
}
}