mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-16 06:28:27 +02:00
feat: add JWT Support to MDM and refacture (MESSENGER-6162)
This commit is contained in:
@@ -173,8 +173,10 @@ class BWIBuildSettings: NSObject {
|
||||
var bwiHashes = [ "a3f65e35a7476799afe8d80282fb3c45b39dab06d1d8c70dc98e45ab7d8e93a9",
|
||||
"2fda1a831655c22a5e6096d7cfbff4429fbf27891141e191b46adbf168142a11",
|
||||
"4f8cbb3fef885f7284d0477d797d7007f0e1ba76221834132752f4d645796e28",
|
||||
/* "24c2ec541e61e8e68944b96dc45ed5df12f6bdbda283cb0b3a522742aa970256", remove internal test server that is handled by token verification*/
|
||||
"1be0b314a6c915d4475290522baef5b642db1b6d68937792b8e0eb5b7b0d6666",
|
||||
/* "24c2ec541e61e8e68944b96dc45ed5df12f6bdbda283cb0b3a522742aa970256",
|
||||
"1be0b314a6c915d4475290522baef5b642db1b6d68937792b8e0eb5b7b0d6666",
|
||||
remove internal test server that is handled by token verification*/
|
||||
|
||||
"3deb73db8cafcd1d5a59e25e251c35816162e1f6ee67b5d7d011da0e8d6ef931",
|
||||
"42e57985d61202c2c7dd87d898cef9bdce020877a4c7a8c7cd699f6a28f58c0c",
|
||||
"e1c3c7cac12bd65bd48de79a2677187d2e768d2769377627534023588b8d7a33",
|
||||
|
||||
@@ -978,17 +978,7 @@
|
||||
|
||||
if (sender == _submitButton)
|
||||
{
|
||||
if (BWIBuildSettings.shared.bwiEnableLoginProtection) {
|
||||
LoginProtectionService* service = [[LoginProtectionService alloc] init];
|
||||
service.hashes = BWIBuildSettings.shared.bwiHashes;
|
||||
if (![service isValid:self->mxRestClient.homeserver]) {
|
||||
NSError *error = [[NSError alloc] initWithDomain:@"LoginProtectionError" code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey: [BWIL10n bwiLoginProtectionErrorMessage:AppInfo.current.displayName]}];
|
||||
[self onFailureDuringAuthRequest:error];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Disable user interaction to prevent multiple requests
|
||||
self.userInteractionEnabled = NO;
|
||||
|
||||
|
||||
@@ -109,3 +109,4 @@ targets:
|
||||
- path: Assets/de.lproj/Vector.strings
|
||||
- path: Assets/de.lproj/Bwi.strings
|
||||
- path: ../publickeys
|
||||
type: folder
|
||||
|
||||
@@ -95,3 +95,4 @@ targets:
|
||||
- path: Assets/de.lproj/Vector.strings
|
||||
- path: Assets/de.lproj/Bwi.strings
|
||||
- path: ../publickeys
|
||||
type: folder
|
||||
|
||||
@@ -68,6 +68,7 @@ targets:
|
||||
- path: ../Config/BuM/BWIBuildSettings+BuM.swift
|
||||
- path: ../bwi/UserAgent/UserAgentService.swift
|
||||
- path: ../bwi/LoginProtection/LoginProtectionService.swift
|
||||
- path: ../bwi/TokenVerification/TokenVerificator.swift
|
||||
- path: ../Config/MDMSettings.swift
|
||||
- path: ../Riot/Utils/DataProtectionHelper.swift
|
||||
- path: ../Config/CommonConfiguration.swift
|
||||
|
||||
@@ -226,37 +226,15 @@ struct AuthenticationServerSelectionScreen: View {
|
||||
}
|
||||
|
||||
private func isHomeserverAddressValid(_ homeserverAddress: String) async -> Bool {
|
||||
|
||||
// bwi #6162 a homeserveraddress is valid when there is either
|
||||
// a) no homeserver protection (bwm)
|
||||
// b) tokenized protection and there is a valid token
|
||||
// c) hashed protection and there is a valid hash (this will be disabled soon)
|
||||
// d) b) && c) can be combined for now
|
||||
if !BWIBuildSettings.shared.bwiEnableTokenizedLoginProtection && !BWIBuildSettings.shared.bwiEnableLoginProtection {
|
||||
return true
|
||||
}
|
||||
|
||||
var validHomeserver = false
|
||||
|
||||
if BWIBuildSettings.shared.bwiEnableTokenizedLoginProtection {
|
||||
|
||||
let tokenVerificator = ServerTokenVerificator()
|
||||
|
||||
let token = await tokenVerificator.fetchToken(baseURL: homeserverAddress)
|
||||
|
||||
if let token = token {
|
||||
validHomeserver = tokenVerificator.verifyToken(baseURL: homeserverAddress, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
if BWIBuildSettings.shared.bwiEnableLoginProtection && !validHomeserver {
|
||||
|
||||
if BWIBuildSettings.shared.bwiEnableLoginProtection || BWIBuildSettings.shared.bwiEnableTokenizedLoginProtection {
|
||||
let protectionService = LoginProtectionService()
|
||||
protectionService.hashes = BWIBuildSettings.shared.bwiHashes
|
||||
|
||||
validHomeserver = protectionService.isValid(homeserverAddress)
|
||||
return await protectionService.isValid(homeserverAddress)
|
||||
}
|
||||
|
||||
return validHomeserver
|
||||
return true
|
||||
}
|
||||
|
||||
/// bwi: jump directly into the iOS settings app to allow camera access
|
||||
|
||||
@@ -76,12 +76,12 @@ extension UserDefaults
|
||||
}
|
||||
}
|
||||
|
||||
private func checkUrlSavety(_ serverUrl: String) -> Bool {
|
||||
private func checkUrlSavety(_ serverUrl: String) async -> Bool {
|
||||
if BWIBuildSettings.shared.bwiEnableLoginProtection {
|
||||
let protectionService = LoginProtectionService()
|
||||
protectionService.hashes = BWIBuildSettings.shared.bwiHashes
|
||||
|
||||
return protectionService.isValid(serverUrl)
|
||||
return await protectionService.isValid(serverUrl)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
@@ -112,11 +112,13 @@ extension UserDefaults
|
||||
|
||||
func registerForAppConfig() {
|
||||
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: OperationQueue.main) { [self] (note) in
|
||||
handleAppConfig()
|
||||
Task {
|
||||
await handleAppConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleAppConfig() {
|
||||
func handleAppConfig() async {
|
||||
if let dict = UserDefaults.standard.dictionary(forKey: configKey) {
|
||||
// only compute if serverURL has not changed (this may need to be changed on Adminportal integration
|
||||
if !isSameConfig(dict: dict) {
|
||||
@@ -125,22 +127,22 @@ extension UserDefaults
|
||||
if let serverUrl = dict[serverUrlKey] as? String {
|
||||
if serverUrl.count == 0 {
|
||||
config.serverUrl = nil
|
||||
} else if checkUrlSavety(serverUrl) {
|
||||
} else if await checkUrlSavety(serverUrl) {
|
||||
config.serverUrl = serverUrl
|
||||
}
|
||||
}
|
||||
if let contentScannerUrl = dict[contentScannerKey] as? String {
|
||||
if checkUrlSavety(contentScannerUrl) {
|
||||
if await checkUrlSavety(contentScannerUrl) {
|
||||
config.contentScannerUrl = contentScannerUrl
|
||||
}
|
||||
}
|
||||
if let pusherUrl = dict[pusherUrlKey] as? String {
|
||||
if checkUrlSavety(pusherUrl) {
|
||||
if await checkUrlSavety(pusherUrl) {
|
||||
config.pusherUrl = pusherUrl
|
||||
}
|
||||
}
|
||||
if let permalinkUrl = dict[permalinkUrlKey] as? String {
|
||||
if checkUrlSavety(permalinkUrl) {
|
||||
if await checkUrlSavety(permalinkUrl) {
|
||||
config.permalinkUrl = permalinkUrl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,36 @@ import CryptoKit
|
||||
@objcMembers class LoginProtectionService : NSObject {
|
||||
var hashes: [String]?
|
||||
|
||||
@objc func isValid(_ urlString: String) -> Bool {
|
||||
guard let hashes = hashes else {
|
||||
return false
|
||||
@objc func isValid(_ homeserverAddress: String) async -> Bool {
|
||||
// bwi #6162 a homeserveraddress is valid when there is either
|
||||
// a) no homeserver protection (bwm)
|
||||
// b) tokenized protection and there is a valid token
|
||||
// c) hashed protection and there is a valid hash (this will be disabled soon)
|
||||
// d) b) && c) can be combined for now
|
||||
|
||||
var validHomeserver = false
|
||||
|
||||
if BWIBuildSettings.shared.bwiEnableTokenizedLoginProtection {
|
||||
|
||||
let tokenVerificator = ServerTokenVerificator()
|
||||
|
||||
let token = await tokenVerificator.fetchToken(baseURL: homeserverAddress)
|
||||
|
||||
if let token = token {
|
||||
validHomeserver = tokenVerificator.verifyToken(baseURL: homeserverAddress, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
let string = self.normalizeLoginUrl(urlString)
|
||||
let hashedString = self.hashedString(string)
|
||||
if BWIBuildSettings.shared.bwiEnableLoginProtection && !validHomeserver {
|
||||
if let hashes = hashes {
|
||||
let string = self.normalizeLoginUrl(homeserverAddress)
|
||||
let hashedString = self.hashedString(string)
|
||||
|
||||
validHomeserver = hashes.contains(hashedString)
|
||||
}
|
||||
}
|
||||
|
||||
return hashes.contains(hashedString)
|
||||
return validHomeserver
|
||||
}
|
||||
|
||||
private func normalizeLoginUrl(_ urlString: String) -> String {
|
||||
|
||||
@@ -16,40 +16,8 @@
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
/*
|
||||
let publicKey: Data = publicKeyStr.data(using: .utf8)!
|
||||
|
||||
struct MyClaims: Claims {
|
||||
let version: Int
|
||||
let hostname: String
|
||||
}
|
||||
|
||||
let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJob3N0bmFtZSI6ImJ3aS5kZSJ9.bondtDczLlOHlHLLZj1C9tn60LqBpIhFNaUy6nYL6CVVwWGIv8EIxYWMTx-MP9OSjj-aeMcy0tmDqSz6nbdbgvUJvkB6r-ByH7fTsVj6OtEEs8mWnqHBOFBwTy9tv5vSTfjFX7PBSko2OK3HQrZkFSkfr-xZoOIc_PxblUnec2hClxVq7ImJnIAW1HCh85DMz2c-MiEHd7wQwBcgwWKWmAY9X6uS25WWhQcPH9i0-QMEQNjXGJp-_wM10KJuuOMDx7QdmcX78QgcOyP-G64cA36NL4-6Aby5EnJUDX-uzFbM_ZERgPVmjfzHoZarFCHSK6-fTBg_MQuDF-O2OOdM6Q"
|
||||
|
||||
let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
|
||||
|
||||
|
||||
|
||||
do {
|
||||
let verified = JWT<MyClaims>.verify(signedJWT, using: jwtVerifier)
|
||||
let newJWT = try JWT<MyClaims>(jwtString: signedJWT, verifier: jwtVerifier)
|
||||
print(newJWT.claims)
|
||||
} catch let error {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
*/
|
||||
|
||||
import SwiftJWT
|
||||
|
||||
/*
|
||||
|
||||
"sub": "1234567890",
|
||||
"name": "John Doe",
|
||||
"admin": true,
|
||||
"iat": 1516239022
|
||||
*/
|
||||
|
||||
struct ServerTokenClaims: Claims {
|
||||
let issuer: String
|
||||
let sub: String
|
||||
@@ -83,12 +51,13 @@ struct ServerTokenVerificator {
|
||||
if verified && (validated == .success) && matchingHomeServer {
|
||||
return true
|
||||
}
|
||||
} catch let error {
|
||||
} catch {
|
||||
// counts like an unverified Token
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
// no public key was able to verify the token
|
||||
return false
|
||||
}
|
||||
|
||||
// fetch the current token from the new endpoint,
|
||||
@@ -104,7 +73,7 @@ struct ServerTokenVerificator {
|
||||
config.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
|
||||
let session : URLSession = URLSession(configuration: config)
|
||||
|
||||
let (data, response) = try await session.data(from: url)
|
||||
let (data, _) = try await session.data(from: url)
|
||||
|
||||
// the token may have additional endlines
|
||||
if let str = String(data: data, encoding: .utf8) {
|
||||
|
||||
Reference in New Issue
Block a user