Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions SmartcarAuth.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
278B07A92248E2E000474A10 /* VehicleInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278B07A82248E2DF00474A10 /* VehicleInfo.swift */; };
535F0D9C362B52F39D5CCCF7 /* Pods_SmartcarAuth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F1C77FCC7CB1C6991212F8 /* Pods_SmartcarAuth.framework */; };
A644ADEA238861F60036CE46 /* SCUrlBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A644ADE9238861F60036CE46 /* SCUrlBuilder.swift */; };
A644ADEC238862810036CE46 /* SCUrlBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A644ADEB238862810036CE46 /* SCUrlBuilderTests.swift */; };
A69F57AB2374EAB9005971D2 /* AuthorizationErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69F57AA2374EAB9005971D2 /* AuthorizationErrorTests.swift */; };
Expand All @@ -33,6 +34,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
19F1C77FCC7CB1C6991212F8 /* Pods_SmartcarAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SmartcarAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; };
278B07A82248E2DF00474A10 /* VehicleInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleInfo.swift; sourceTree = "<group>"; };
41E81CE39269597B8418C7C0 /* Pods-SmartcarAuth.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SmartcarAuth.release.xcconfig"; path = "Pods/Target Support Files/Pods-SmartcarAuth/Pods-SmartcarAuth.release.xcconfig"; sourceTree = "<group>"; };
4C65C9D0D291B77BE47281A0 /* Pods_SmartcarAuthTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SmartcarAuthTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -59,6 +61,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
535F0D9C362B52F39D5CCCF7 /* Pods_SmartcarAuth.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -78,6 +81,7 @@
isa = PBXGroup;
children = (
4C65C9D0D291B77BE47281A0 /* Pods_SmartcarAuthTests.framework */,
19F1C77FCC7CB1C6991212F8 /* Pods_SmartcarAuth.framework */,
);
name = Frameworks;
sourceTree = "<group>";
Expand Down Expand Up @@ -204,7 +208,6 @@
TargetAttributes = {
F8F928801E2B2F6A009F07E5 = {
CreatedOnToolsVersion = 8.2;
DevelopmentTeam = EE32J27TKP;
LastSwiftMigration = 1120;
ProvisioningStyle = Automatic;
};
Expand Down Expand Up @@ -465,9 +468,10 @@
baseConfigurationReference = 8364B99DE3988F4714D06ED1 /* Pods-SmartcarAuth.debug.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = EE32J27TKP;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
Expand All @@ -479,6 +483,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.smartcar.SmartCarOAuthSDK;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
Expand All @@ -491,9 +496,10 @@
baseConfigurationReference = 41E81CE39269597B8418C7C0 /* Pods-SmartcarAuth.release.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = EE32J27TKP;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
Expand All @@ -505,6 +511,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.smartcar.SmartCarOAuthSDK;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 5.0;
Expand Down
6 changes: 3 additions & 3 deletions SmartcarAuth/SCUrlBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- clientId: The application's client ID
- redirectUri: The application's redirect URI
- scope: An array of authorization scopes
- testMode: Optional, launch the Smartcar auth flow in test mode when set to true. Defaults to false.
- authMode: Launch the Smartcar auth flow with the corresponding mode. Defaults to test mode.
*/
public init(clientId: String, redirectUri: String, scope: [String], testMode: Bool) {
public init(clientId: String, redirectUri: String, scope: [String], authMode: SmartcarAuthMode) {
self.components = URLComponents()
self.components.scheme = "https"
self.components.host = "connect.smartcar.com"
Expand All @@ -43,7 +43,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
self.queryItems.append(contentsOf: [
URLQueryItem(name: "client_id", value: clientId),
URLQueryItem(name: "response_type", value: "code"),
URLQueryItem(name: "mode", value: testMode ? "test" : "live")
URLQueryItem(name: "mode", value: authMode.rawValue)
])

if let redirectUri = redirectUri.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
Expand Down
16 changes: 11 additions & 5 deletions SmartcarAuth/SmartcarAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,23 @@ import SafariServices
import AuthenticationServices
#endif

public enum SmartcarAuthMode: String {
case live
case test
case simulated
}

/**
Smartcar Authentication SDK for iOS written in Swift 5.
- Facilitates the authorization flow to launch the flow and retrieve an authorization code
*/
@objcMembers public class SmartcarAuth: NSObject {

var clientId: String
var redirectUri: String
var scope: [String]
var completionHandler: (_ code: String?, _ state: String?, _ error: AuthorizationError?) -> Void
var testMode: Bool
var authMode: SmartcarAuthMode

// SFAuthenticationSession/ASWebAuthenticationSession require a strong reference to the session so that the system doesn't deallocate the session before the user finishes authenticating
private var session: Session?
Expand All @@ -47,14 +53,14 @@ Smartcar Authentication SDK for iOS written in Swift 5.
- clientId: The application's client ID
- redirectUri: The application's redirect URI
- scope: An array of authorization scopes
- testMode: Optional, launch the Smartcar auth flow in test mode when set to true. Defaults to false.
- authMode: Launch the Smartcar auth flow with the corresponding mode. Defaults to test mode.
- completion: Callback function called upon the completion of the Smartcar Connect
*/
public init(clientId: String, redirectUri: String, scope: [String], completionHandler: @escaping (String?, String?, AuthorizationError?) -> Void, testMode: Bool = false) {
public init(clientId: String, redirectUri: String, scope: [String], completionHandler: @escaping (String?, String?, AuthorizationError?) -> Void, authMode: SmartcarAuthMode = .test) {
self.clientId = clientId
self.redirectUri = redirectUri
self.scope = scope
self.testMode = testMode
self.authMode = authMode
self.completionHandler = completionHandler
}

Expand All @@ -63,7 +69,7 @@ Smartcar Authentication SDK for iOS written in Swift 5.
See `SCURLBuilder` for a full list of query parameters that can be set on the authorization URL
*/
public func authUrlBuilder() -> SCUrlBuilder {
return SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
return SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
}

/**
Expand Down
26 changes: 13 additions & 13 deletions SmartcarAuthTests/SCUrlBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SCUrlBuilderTests: XCTestCase {
let make = "TESLA"
let vin = "12345678901234567"
let flags = ["country:DE", "flag:suboption"]
var testMode = false
var authMode = SmartcarAuthMode.live

override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
Expand All @@ -31,24 +31,24 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderBaseUrlLiveMode() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer"

let baseUrl = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode).build()
let baseUrl = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode).build()

expect(baseUrl).to(equal(expectedUrl))
}

func testSCUrlBuilderBaseUrlTestMode() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=test&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer"
self.testMode = true
self.authMode = .test

let baseUrl = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode).build()
let baseUrl = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode).build()

expect(baseUrl).to(equal(expectedUrl))
}

func testSCUrlBuilderSetState() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&state=" + state

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setState(state: state)
.build()

Expand All @@ -58,7 +58,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetForcePromptTrue() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&approval_prompt=force"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setForcePrompt(forcePrompt: true)
.build()

Expand All @@ -68,7 +68,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetForcePromptFalse() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&approval_prompt=auto"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setForcePrompt(forcePrompt: false)
.build()

Expand All @@ -78,7 +78,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetMakeBypass() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&make=TESLA"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setMakeBypass(make: make)
.build()

Expand All @@ -88,7 +88,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetSingleSelectTrue() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&single_select=true"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setSingleSelect(singleSelect: true)
.build()

Expand All @@ -98,7 +98,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetSingleSelectFalse() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&single_select=false"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setSingleSelect(singleSelect: false)
.build()

Expand All @@ -108,7 +108,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetSingleSelectVin() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&single_select=true&single_select_vin=12345678901234567"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setSingleSelect(singleSelect: true)
.setSingleSelectVin(vin: vin)
.build()
Expand All @@ -119,7 +119,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetFlags() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&flags=country:DE%20flag:suboption"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setFlags(flags: flags)
.build()

Expand All @@ -129,7 +129,7 @@ class SCUrlBuilderTests: XCTestCase {
func testSCUrlBuilderSetAllParameters() {
let expectedUrl = "https://connect.smartcar.com/oauth/authorize?client_id=" + clientId + "&response_type=code&mode=live&redirect_uri=" + redirectUri + "&scope=read_vehicle_info%20read_odometer&state=" + state + "&approval_prompt=force&make=TESLA&single_select=true&single_select_vin=12345678901234567&flags=country:DE%20flag:suboption"

let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, testMode: testMode)
let urlWithState = SCUrlBuilder(clientId: clientId, redirectUri: redirectUri, scope: scope, authMode: authMode)
.setState(state: state)
.setForcePrompt(forcePrompt: true)
.setMakeBypass(make: make)
Expand Down