Skip to content

Commit

Permalink
Merge pull request #304 from ForgeRock/SDKS-3352-expose-successUrl-realm
Browse files Browse the repository at this point in the history
Expose success url and realm in getSessionToken
  • Loading branch information
spetrov authored Sep 16, 2024
2 parents e140b77 + 074683a commit fadcf07
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 34 deletions.
6 changes: 4 additions & 2 deletions FRAuth/FRAuth/Authentication/AuthService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// AuthService.swift
// FRAuth
//
// Copyright (c) 2019-2021 ForgeRock. All rights reserved.
// Copyright (c) 2019-2024 ForgeRock. All rights reserved.
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -229,7 +229,9 @@ public class AuthService: NSObject {
}
}
else if let tokenId = response[OpenAM.tokenId] as? String {
let token = Token(tokenId)
let successUrl = response[OpenAM.successUrl] as? String ?? ""
let realm = response[OpenAM.realm] as? String ?? ""
let token = Token(tokenId, successUrl: successUrl, realm: realm)
if let keychainManager = self.keychainManager {
let currentSessionToken = keychainManager.getSSOToken()
if let _ = try? keychainManager.getAccessToken(), token.value != currentSessionToken?.value {
Expand Down
4 changes: 3 additions & 1 deletion FRAuth/FRAuth/Authentication/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ public class Node: NSObject {
}
}
else if let tokenId = response[OpenAM.tokenId] as? String {
let token = Token(tokenId)
let successUrl = response[OpenAM.successUrl] as? String ?? ""
let realm = response[OpenAM.realm] as? String ?? ""
let token = Token(tokenId, successUrl: successUrl, realm: realm)
if let keychainManager = self.keychainManager {
let currentSessionToken = keychainManager.getSSOToken()
if let _ = try? keychainManager.getAccessToken(), token.value != currentSessionToken?.value {
Expand Down
4 changes: 3 additions & 1 deletion FRAuth/FRAuth/Constants/OpenAM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// OpenAM.swift
// FRAuth
//
// Copyright (c) 2019-2020 ForgeRock. All rights reserved.
// Copyright (c) 2019-2024 ForgeRock. All rights reserved.
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -30,4 +30,6 @@ struct OpenAM {
static let xRequestedWith = "X-Requested-With"
static let xmlHTTPRequest = "XMLHTTPRequest"
static let suspendedId = "suspendedId"
static let successUrl = "successUrl"
static let realm = "realm"
}
12 changes: 10 additions & 2 deletions FRAuth/FRAuth/Manager/KeychainManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// KeychainManager.swift
// FRAuth
//
// Copyright (c) 2019-2022 ForgeRock. All rights reserved.
// Copyright (c) 2019-2024 ForgeRock. All rights reserved.
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -30,6 +30,8 @@ struct KeychainManager {
case ssoToken = "sso_token"
case primaryService = "primaryService"
case primaryServiceEncrypted = "primaryService-encrypted"
case successUrl = "successUrl"
case realm = "realm"
}

/// String constant for SecuredKey's application tag
Expand Down Expand Up @@ -155,7 +157,9 @@ struct KeychainManager {
/// Returns current session's Token object that represents SSO Token
func getSSOToken() -> Token? {
if let ssoTokenString = self.sharedStore.getString(StorageKey.ssoToken.rawValue) {
return Token(ssoTokenString)
let successUrl = self.sharedStore.getString(StorageKey.successUrl.rawValue) ?? ""
let realm = self.sharedStore.getString(StorageKey.realm.rawValue) ?? ""
return Token(ssoTokenString, successUrl: successUrl, realm: realm)
}
else {
return nil
Expand All @@ -169,9 +173,13 @@ struct KeychainManager {
@discardableResult func setSSOToken(ssoToken: Token?) -> Bool {
if let token = ssoToken {
return self.sharedStore.set(token.value, key: StorageKey.ssoToken.rawValue)
&& self.sharedStore.set(token.successUrl, key: StorageKey.successUrl.rawValue)
&& self.sharedStore.set(token.realm, key: StorageKey.realm.rawValue)
}
else {
return self.sharedStore.delete(StorageKey.ssoToken.rawValue)
&& self.sharedStore.delete(StorageKey.successUrl.rawValue)
&& self.sharedStore.delete(StorageKey.realm.rawValue)
}
}

Expand Down
18 changes: 14 additions & 4 deletions FRAuth/FRAuth/OAuth2/Token.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Token.swift
// FRAuth
//
// Copyright (c) 2019-2021 ForgeRock. All rights reserved.
// Copyright (c) 2019-2024 ForgeRock. All rights reserved.
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
Expand All @@ -18,15 +18,21 @@ import Foundation
/// Raw value of token
@objc
public var value: String
public var successUrl: String
public var realm: String


// MARK: - Init

/// Initializes Token object with given token value
///
/// - Parameter token: raw string value of token
init(_ token: String) {
init(_ token: String,
successUrl: String = "",
realm: String = "") {
self.value = token
self.successUrl = successUrl
self.realm = realm
super.init()
}

Expand All @@ -51,10 +57,12 @@ import Foundation
///
/// - Parameter aDecoder: NSCoder
convenience required public init?(coder aDecoder: NSCoder) {
guard let token = aDecoder.decodeObject(of: NSString.self, forKey: "value") as String? else {
guard let token = aDecoder.decodeObject(of: NSString.self, forKey: "value") as String?,
let successUrl = aDecoder.decodeObject(of: NSString.self, forKey: "successUrl") as String?,
let realm = aDecoder.decodeObject(of: NSString.self, forKey: "realm") as String? else {
return nil
}
self.init(token)
self.init(token, successUrl: successUrl, realm: realm)
}


Expand All @@ -63,6 +71,8 @@ import Foundation
/// - Parameter aCoder: NSCoder
public func encode(with aCoder: NSCoder) {
aCoder.encode(self.value, forKey: "value")
aCoder.encode(self.successUrl, forKey: "successUrl")
aCoder.encode(self.realm, forKey: "realm")
}


Expand Down
125 changes: 101 additions & 24 deletions FRAuth/FRAuthTests/FRAuthSwiftTests/FRAuth/Model/OAuth2/TokenTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// TokenTests.swift
// FRAuthTests
//
// Copyright (c) 2019-2021 ForgeRock. All rights reserved.
// Copyright (c) 2019-2024 ForgeRock. All rights reserved.
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
Expand All @@ -12,14 +12,26 @@ import XCTest
@testable import FRAuth

class TokenTests: FRAuthBaseTest {

func testBasicTokenValue() {

// Given
let token = Token("tokenValue")

// Then
XCTAssertEqual(token.value, "tokenValue")
XCTAssertEqual(token.successUrl, "")
XCTAssertEqual(token.realm, "")
}

func testBasicTokenValueWithoutDefaultValues() {

// Given
let token = Token("tokenValue", successUrl: "http://success.url", realm: "myRealm")

// Then
XCTAssertEqual(token.value, "tokenValue")
XCTAssertEqual(token.successUrl, "http://success.url")
XCTAssertEqual(token.realm, "myRealm")
}

func testBasicTokenDebugDescription() {
Expand All @@ -33,33 +45,62 @@ class TokenTests: FRAuthBaseTest {


func testTokenSecureCoding() {
if #available(iOS 11.0, *) {
// Given
let token = Token("tokenValue")

// Given
let token = Token("tokenValue")

// Then
XCTAssertEqual(token.value, "tokenValue")

// Should Also
do {
// With given
let tokenData = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true)

// Then
XCTAssertEqual(token.value, "tokenValue")

// Should Also
do {
// With given
let tokenData = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true)

// Then
if let token2 = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [AccessToken.self, Token.self], from: tokenData) as? Token {
// Should equal
XCTAssertEqual(token2, token)
XCTAssertTrue(token2 == token)
XCTAssertEqual(token2.value, "tokenValue")
}
else {
XCTFail("Failed to unarchive AccessToken \nToken:\(token.debugDescription)\n\nToken Data: \(tokenData)")
}
if let token2 = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [AccessToken.self, Token.self], from: tokenData) as? Token {
// Should equal
XCTAssertEqual(token2, token)
XCTAssertTrue(token2 == token)
XCTAssertEqual(token2.value, "tokenValue")
}
catch {
XCTFail("Failed to archive AccessToken \nError:\(error.localizedDescription)\n\nToken:\(token.debugDescription)")
else {
XCTFail("Failed to unarchive AccessToken \nToken:\(token.debugDescription)\n\nToken Data: \(tokenData)")
}
}
catch {
XCTFail("Failed to archive AccessToken \nError:\(error.localizedDescription)\n\nToken:\(token.debugDescription)")
}
}

func testTokenSecureCodingWithoutDefaultValues() {

// Given
let token = Token("tokenValue", successUrl: "http://success.url", realm: "myRealm")

// Then
XCTAssertEqual(token.value, "tokenValue")

// Should Also
do {
// With given
let tokenData = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true)

// Then
if let token2 = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [AccessToken.self, Token.self], from: tokenData) as? Token {
// Should equal
XCTAssertEqual(token2, token)
XCTAssertTrue(token2 == token)
XCTAssertEqual(token2.value, "tokenValue")
XCTAssertEqual(token2.successUrl, "http://success.url")
XCTAssertEqual(token2.realm, "myRealm")
}
else {
XCTFail("Failed to unarchive AccessToken \nToken:\(token.debugDescription)\n\nToken Data: \(tokenData)")
}
}
catch {
XCTFail("Failed to archive AccessToken \nError:\(error.localizedDescription)\n\nToken:\(token.debugDescription)")
}
}

Expand Down Expand Up @@ -90,4 +131,40 @@ class TokenTests: FRAuthBaseTest {
XCTFail("Fail to create AccessToken JSON String with given data")
}
}

func testTokenJSONEncodingWithoutDefaultValues() {

let token = Token("tokenValue", successUrl: "http://success.url", realm: "myRealm")

// Then
XCTAssertEqual(token.value, "tokenValue")
XCTAssertEqual(token.successUrl, "http://success.url")
XCTAssertEqual(token.realm, "myRealm")

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

let data = try? encoder.encode(token)
XCTAssertNotNil(data)

if let tokenData = data, let jsonToken = String(data: tokenData, encoding: .utf8) {
let tokenDictionary = self.parseStringToDictionary(jsonToken)
XCTAssertNotNil(tokenDictionary)

if let token2Value = tokenDictionary["value"] as? String,
let token2SuccessUrl = tokenDictionary["successUrl"] as? String,
let token2Realm = tokenDictionary["realm"] as? String {
XCTAssertEqual(token2Value, token.value)
XCTAssertEqual(token2Value, "tokenValue")
XCTAssertEqual(token2SuccessUrl, token.successUrl)
XCTAssertEqual(token2SuccessUrl, "http://success.url")
XCTAssertEqual(token2Realm, token.realm)
XCTAssertEqual(token2Realm, "myRealm")
} else {
XCTFail("Fail to parse AccessToken JSON String correctly with given data \(jsonToken)")
}
} else {
XCTFail("Fail to create AccessToken JSON String with given data")
}
}
}

0 comments on commit fadcf07

Please sign in to comment.