Skip to content

Commit

Permalink
fix: saml sso review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
RawanMatar89 committed Oct 21, 2024
1 parent 04708ea commit e1ba302
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public class SignInViewModel: ObservableObject {
analytics.userSignInClicked()
isShowProgress = true
do {
let user = try await interactor.SSOlogin(jwtToken: "239i2oi3jrf2jflkj23lf2f")
let user = try await interactor.SSOlogin(jwtToken: "")
analytics.identify(id: "\(user.id)", username: user.username, email: user.email)
analytics.userLogin(method: .password)
router.showMainOrWhatsNewScreen(sourceScreen: sourceScreen)
Expand Down
33 changes: 20 additions & 13 deletions Authorization/Authorization/Presentation/SSO/SSOHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
import KeychainSwift

// https://developer.apple.com/documentation/ios-ipados-release-notes/foundation-release-notes

Expand All @@ -15,7 +16,8 @@ import Foundation
*/
public class SSOHelper: NSObject {

public enum UserDefaultKeys: String, CaseIterable {
private let keychain: KeychainSwift
public enum SSOHelperKeys: String, CaseIterable {
case cookiePayload
case cookieSignature
case userInfo
Expand All @@ -31,34 +33,39 @@ public class SSOHelper: NSObject {
}
}
}

// MARK: - Singleton

public static let shared = SSOHelper()

public init(keychain: KeychainSwift) {
self.keychain = keychain
}
// MARK: - Public Properties

/// Authentication
public var cookiePayload: String? {
get {
let defaults = UserDefaults.standard
return defaults.string(forKey: UserDefaultKeys.cookiePayload.rawValue)
return keychain.get(SSOHelperKeys.cookiePayload.rawValue)
}
set (newValue) {
let defaults = UserDefaults.standard
defaults.set(newValue, forKey: UserDefaultKeys.cookiePayload.rawValue)
set(newValue) {
if let newValue {
keychain.set(newValue, forKey: SSOHelperKeys.cookiePayload.rawValue)
} else {
keychain.delete(SSOHelperKeys.cookiePayload.rawValue)
}
}
}

/// Authentication
public var cookieSignature: String? {
get {
let defaults = UserDefaults.standard
return defaults.string(forKey: UserDefaultKeys.cookieSignature.rawValue)
return keychain.get(SSOHelperKeys.cookieSignature.rawValue)
}
set (newValue) {
let defaults = UserDefaults.standard
defaults.set(newValue, forKey: UserDefaultKeys.cookieSignature.rawValue)
set(newValue) {
if let newValue {
keychain.set(newValue, forKey: SSOHelperKeys.cookieSignature.rawValue)
} else {
keychain.delete(SSOHelperKeys.cookieSignature.rawValue)
}
}
}

Expand Down
29 changes: 8 additions & 21 deletions Authorization/Authorization/Presentation/SSO/SSOWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,10 @@
//
// Created by Rawan Matar on 02/06/2024.
//


import SwiftUI
import WebKit
@preconcurrency import WebKit
import Core

public struct SAMLConstants {

public init() {}

public let samlLoginSuccess = URL(string: "https://blue.zeitlabs.com/auth/complete/tpa-saml")!
}

public struct SSOWebView: UIViewRepresentable {

let url: URL?
Expand Down Expand Up @@ -69,28 +60,24 @@ public struct SSOWebView: UIViewRepresentable {
super.init()
}

// WKScriptMessageHandler
public func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
// WKScriptMessageHandler
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
}

// WKNavigationDelegate
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
guard let _ = webView.url?.absoluteString else {
if webView.url?.absoluteString == nil {
return
}

}

public func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = webView.url?.absoluteString else {
decisionHandler(.allow)
return
}

if url.contains(SAMLConstants().samlLoginSuccess.absoluteString) {
if url.contains(viewModel.config.successfulSSOURLLogin.absoluteString) {
webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
Task {
await self.viewModel.SSOLogin(cookies: cookies)
Expand Down
19 changes: 11 additions & 8 deletions Authorization/Authorization/Presentation/SSO/SSOWebViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,20 @@ public class SSOWebViewModel: ObservableObject {
let config: ConfigProtocol
private let interactor: AuthInteractorProtocol
private let analytics: AuthorizationAnalytics

let ssoHelper: SSOHelper

public init(
interactor: AuthInteractorProtocol,
router: AuthorizationRouter,
config: ConfigProtocol,
analytics: AuthorizationAnalytics
analytics: AuthorizationAnalytics,
ssoHelper: SSOHelper
) {
self.interactor = interactor
self.router = router
self.config = config
self.analytics = analytics
self.ssoHelper = ssoHelper
}

@MainActor
Expand All @@ -64,15 +67,15 @@ public class SSOWebViewModel: ObservableObject {
for cookie in cookies {

/// Store cookies in UserDefaults
if cookie.name == SSOHelper.UserDefaultKeys.cookiePayload.description {
SSOHelper.shared.cookiePayload = cookie.value
if cookie.name == SSOHelper.SSOHelperKeys.cookiePayload.description {
self.ssoHelper.cookiePayload = cookie.value
}

if cookie.name == SSOHelper.UserDefaultKeys.cookieSignature.description {
SSOHelper.shared.cookieSignature = cookie.value
if cookie.name == SSOHelper.SSOHelperKeys.cookieSignature.description {
self.ssoHelper.cookieSignature = cookie.value
}
if let signature = SSOHelper.shared.cookieSignature,
let payload = SSOHelper.shared.cookiePayload {
if let signature = self.ssoHelper.cookieSignature,
let payload = self.ssoHelper.cookiePayload {
isShowProgress = true
do {
let user = try await interactor.SSOlogin(jwtToken: "\(payload).\(signature)")
Expand Down
10 changes: 10 additions & 0 deletions Core/Core/Configuration/Config/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Foundation
public protocol ConfigProtocol {
var baseURL: URL { get }
var baseSSOURL: URL { get }
var successfulSSOURLLogin: URL { get }
var ssoButtonTitle: [String: Any] { get }
var oAuthClientId: String { get }
var tokenType: TokenType { get }
Expand Down Expand Up @@ -44,6 +45,7 @@ public enum TokenType: String {
private enum ConfigKeys: String {
case baseURL = "API_HOST_URL"
case SSOBaseURL = "SSO_URL"
case SuccessfulSSOLoginURL = "SSO_URL_SUCCESSFUL_LOGIN"
case ssoButtonTitle = "SSO_BUTTON_TITLE"
case oAuthClientID = "OAUTH_CLIENT_ID"
case tokenType = "TOKEN_TYPE"
Expand Down Expand Up @@ -132,6 +134,14 @@ extension Config: ConfigProtocol {
return url
}

public var successfulSSOURLLogin: URL {
guard let urlString = string(for: ConfigKeys.SuccessfulSSOLoginURL.rawValue),
let url = URL(string: urlString) else {
fatalError("Unable to find SSO successful login url in config.")
}
return url
}

public var ssoButtonTitle: [String: Any] {
guard let ssoButtonTitle = dict(for: ConfigKeys.ssoButtonTitle.rawValue) else {
return ["en": CoreLocalization.SignIn.logInWithSsoBtn]
Expand Down
6 changes: 6 additions & 0 deletions OpenEdX/DI/AppAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ class AppAssembly: Assembly {
r.resolve(AppStorage.self)!
}.inObjectScope(.container)

container.register(SSOHelper.self){ r in
SSOHelper(
keychain: r.resolve(KeychainSwift.self)!
)
}

container.register(Validator.self) { _ in
Validator()
}.inObjectScope(.container)
Expand Down
3 changes: 2 additions & 1 deletion OpenEdX/DI/ScreenAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ class ScreenAssembly: Assembly {
interactor: r.resolve(AuthInteractorProtocol.self)!,
router: r.resolve(AuthorizationRouter.self)!,
config: r.resolve(ConfigProtocol.self)!,
analytics: r.resolve(AuthorizationAnalytics.self)!
analytics: r.resolve(AuthorizationAnalytics.self)!,
ssoHelper: r.resolve(SSOHelper.self)!
)
}
container.register(SignUpViewModel.self) { r, sourceScreen in
Expand Down
1 change: 1 addition & 0 deletions default_config/dev/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
API_HOST_URL: 'http://localhost:8000'
SSO_URL: 'http://localhost:8000'
SSO_URL_SUCCESSFUL_LOGIN: 'http://localhost:8000'
ENVIRONMENT_DISPLAY_NAME: 'Localhost'
FEEDBACK_EMAIL_ADDRESS: '[email protected]'
OAUTH_CLIENT_ID: ''
Expand Down

0 comments on commit e1ba302

Please sign in to comment.