Skip to content

Commit 356b7e9

Browse files
committed
Some updates, add a workspace, add shared schemes, update Playground stub
1 parent b30c910 commit 356b7e9

File tree

10 files changed

+256
-46
lines changed

10 files changed

+256
-46
lines changed

OAuth2 Tests/OAuth2CodeGrant_tests.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class OAuth2CodeGrantTests: XCTestCase {
5050
XCTAssertNil(query["client_secret"], "Must not have `client_secret`")
5151
XCTAssertEqual(query["response_type"]!, "code", "Expecting correct `response_type`")
5252
XCTAssertEqual(query["redirect_uri"]!, "oauth2://callback", "Expecting correct `redirect_uri`")
53-
XCTAssertTrue(36 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
53+
XCTAssertTrue(8 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
5454

5555
// TODO: test for non-https URLs (must raise)
5656
}
@@ -74,7 +74,7 @@ class OAuth2CodeGrantTests: XCTestCase {
7474
XCTAssertEqual(query["code"]!, "pp", "Expecting correct `code`")
7575
XCTAssertEqual(query["grant_type"]!, "authorization_code", "Expecting correct `grant_type`")
7676
XCTAssertEqual(query["redirect_uri"]!, "oauth2://callback", "Expecting correct `redirect_uri`")
77-
XCTAssertTrue(36 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
77+
XCTAssertTrue(8 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
7878

7979
// test authURL fallback
8080
oauth = OAuth2CodeGrant(settings: [
@@ -100,14 +100,14 @@ class OAuth2CodeGrantTests: XCTestCase {
100100
oauth.redirect = "oauth2://callback"
101101

102102
let req = oauth.tokenRequest("pp")
103-
let body = NSString(data: req.HTTPBody, encoding: NSUTF8StringEncoding)
103+
let body = NSString(data: req.HTTPBody!, encoding: NSUTF8StringEncoding)
104104
let query = OAuth2CodeGrant.paramsFromQuery(body)
105105
XCTAssertEqual(query["client_id"]!, "abc", "Expecting correct `client_id`")
106106
XCTAssertEqual(query["client_secret"]!, "xyz", "Expecting correct `client_secret`")
107107
XCTAssertEqual(query["code"]!, "pp", "Expecting correct `code`")
108108
XCTAssertEqual(query["grant_type"]!, "authorization_code", "Expecting correct `grant_type`")
109109
XCTAssertEqual(query["redirect_uri"]!, "oauth2://callback", "Expecting correct `redirect_uri`")
110-
XCTAssertTrue(36 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
110+
XCTAssertTrue(8 == countElements(query["state"]!), "Expecting an auto-generated UUID for `state`")
111111
}
112112

113113
/*func testPerformanceExample() {

OAuth2.xcodeproj/project.pbxproj

-6
Original file line numberDiff line numberDiff line change
@@ -520,15 +520,10 @@
520520
DYLIB_CURRENT_VERSION = 1;
521521
DYLIB_INSTALL_NAME_BASE = "@rpath";
522522
FRAMEWORK_VERSION = A;
523-
GCC_PREPROCESSOR_DEFINITIONS = (
524-
"DEBUG=1",
525-
"$(inherited)",
526-
);
527523
INFOPLIST_FILE = OAuth2/Info.plist;
528524
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
529525
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
530526
MACOSX_DEPLOYMENT_TARGET = 10.9;
531-
METAL_ENABLE_DEBUG_INFO = YES;
532527
PRODUCT_NAME = OAuth2;
533528
SDKROOT = macosx;
534529
SKIP_INSTALL = YES;
@@ -549,7 +544,6 @@
549544
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
550545
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
551546
MACOSX_DEPLOYMENT_TARGET = 10.9;
552-
METAL_ENABLE_DEBUG_INFO = NO;
553547
PRODUCT_NAME = OAuth2;
554548
SDKROOT = macosx;
555549
SKIP_INSTALL = YES;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "0600"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "EEE209461942772800736F1A"
18+
BuildableName = "OAuth2.framework"
19+
BlueprintName = "OAuth2"
20+
ReferencedContainer = "container:OAuth2.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
<BuildActionEntry
24+
buildForTesting = "YES"
25+
buildForRunning = "YES"
26+
buildForProfiling = "NO"
27+
buildForArchiving = "NO"
28+
buildForAnalyzing = "YES">
29+
<BuildableReference
30+
BuildableIdentifier = "primary"
31+
BlueprintIdentifier = "EEE209A119427DFE00736F1A"
32+
BuildableName = "OAuth2 Tests.xctest"
33+
BlueprintName = "OAuth2 Tests"
34+
ReferencedContainer = "container:OAuth2.xcodeproj">
35+
</BuildableReference>
36+
</BuildActionEntry>
37+
</BuildActionEntries>
38+
</BuildAction>
39+
<TestAction
40+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
41+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
42+
shouldUseLaunchSchemeArgsEnv = "YES"
43+
buildConfiguration = "Debug">
44+
<Testables>
45+
<TestableReference
46+
skipped = "NO">
47+
<BuildableReference
48+
BuildableIdentifier = "primary"
49+
BlueprintIdentifier = "EEE209A119427DFE00736F1A"
50+
BuildableName = "OAuth2 Tests.xctest"
51+
BlueprintName = "OAuth2 Tests"
52+
ReferencedContainer = "container:OAuth2.xcodeproj">
53+
</BuildableReference>
54+
</TestableReference>
55+
</Testables>
56+
<MacroExpansion>
57+
<BuildableReference
58+
BuildableIdentifier = "primary"
59+
BlueprintIdentifier = "EEE209461942772800736F1A"
60+
BuildableName = "OAuth2.framework"
61+
BlueprintName = "OAuth2"
62+
ReferencedContainer = "container:OAuth2.xcodeproj">
63+
</BuildableReference>
64+
</MacroExpansion>
65+
</TestAction>
66+
<LaunchAction
67+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
68+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
69+
launchStyle = "0"
70+
useCustomWorkingDirectory = "NO"
71+
buildConfiguration = "Debug"
72+
ignoresPersistentStateOnLaunch = "NO"
73+
debugDocumentVersioning = "YES"
74+
allowLocationSimulation = "YES">
75+
<MacroExpansion>
76+
<BuildableReference
77+
BuildableIdentifier = "primary"
78+
BlueprintIdentifier = "EEE209461942772800736F1A"
79+
BuildableName = "OAuth2.framework"
80+
BlueprintName = "OAuth2"
81+
ReferencedContainer = "container:OAuth2.xcodeproj">
82+
</BuildableReference>
83+
</MacroExpansion>
84+
<AdditionalOptions>
85+
</AdditionalOptions>
86+
</LaunchAction>
87+
<ProfileAction
88+
shouldUseLaunchSchemeArgsEnv = "YES"
89+
savedToolIdentifier = ""
90+
useCustomWorkingDirectory = "NO"
91+
buildConfiguration = "Release"
92+
debugDocumentVersioning = "YES">
93+
<MacroExpansion>
94+
<BuildableReference
95+
BuildableIdentifier = "primary"
96+
BlueprintIdentifier = "EEE209461942772800736F1A"
97+
BuildableName = "OAuth2.framework"
98+
BlueprintName = "OAuth2"
99+
ReferencedContainer = "container:OAuth2.xcodeproj">
100+
</BuildableReference>
101+
</MacroExpansion>
102+
</ProfileAction>
103+
<AnalyzeAction
104+
buildConfiguration = "Debug">
105+
</AnalyzeAction>
106+
<ArchiveAction
107+
buildConfiguration = "Release"
108+
revealArchiveInOrganizer = "YES">
109+
</ArchiveAction>
110+
</Scheme>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "0600"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "EEDB8623193FAAE500C4EEA1"
18+
BuildableName = "OAuth2iOS.framework"
19+
BlueprintName = "OAuth2iOS"
20+
ReferencedContainer = "container:OAuth2.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28+
shouldUseLaunchSchemeArgsEnv = "YES"
29+
buildConfiguration = "Debug">
30+
<Testables>
31+
</Testables>
32+
</TestAction>
33+
<LaunchAction
34+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36+
launchStyle = "0"
37+
useCustomWorkingDirectory = "NO"
38+
buildConfiguration = "Debug"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
allowLocationSimulation = "YES">
42+
<MacroExpansion>
43+
<BuildableReference
44+
BuildableIdentifier = "primary"
45+
BlueprintIdentifier = "EEDB8623193FAAE500C4EEA1"
46+
BuildableName = "OAuth2iOS.framework"
47+
BlueprintName = "OAuth2iOS"
48+
ReferencedContainer = "container:OAuth2.xcodeproj">
49+
</BuildableReference>
50+
</MacroExpansion>
51+
<AdditionalOptions>
52+
</AdditionalOptions>
53+
</LaunchAction>
54+
<ProfileAction
55+
shouldUseLaunchSchemeArgsEnv = "YES"
56+
savedToolIdentifier = ""
57+
useCustomWorkingDirectory = "NO"
58+
buildConfiguration = "Release"
59+
debugDocumentVersioning = "YES">
60+
<MacroExpansion>
61+
<BuildableReference
62+
BuildableIdentifier = "primary"
63+
BlueprintIdentifier = "EEDB8623193FAAE500C4EEA1"
64+
BuildableName = "OAuth2iOS.framework"
65+
BlueprintName = "OAuth2iOS"
66+
ReferencedContainer = "container:OAuth2.xcodeproj">
67+
</BuildableReference>
68+
</MacroExpansion>
69+
</ProfileAction>
70+
<AnalyzeAction
71+
buildConfiguration = "Debug">
72+
</AnalyzeAction>
73+
<ArchiveAction
74+
buildConfiguration = "Release"
75+
revealArchiveInOrganizer = "YES">
76+
</ArchiveAction>
77+
</Scheme>

OAuth2.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

OAuth2/OAuth2.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public class OAuth2 {
4646
/** The redirect URL string currently in use. */
4747
public var redirect: String?
4848

49-
/** The state sent to the server when requesting a token; we internally generate a UUID unless it's set manually. */
49+
/** The state sent to the server when requesting a token.
50+
* We internally generate a UUID and use the first 8 chars. */
5051
var state = ""
5152

5253
/** The receiver's access token. */
@@ -147,8 +148,10 @@ public class OAuth2 {
147148

148149
if state.isEmpty {
149150
state = NSUUID().UUIDString
151+
state = state[state.startIndex..<advance(state.startIndex, 8)] // only use the first 8 chars, should be enough
150152
}
151153

154+
152155
// compose the URL
153156
let comp = NSURLComponents(URL: base, resolvingAgainstBaseURL: true)
154157
assert("https" == comp.scheme, "You MUST use HTTPS")

OAuth2/OAuth2CodeGrant.swift

+13-7
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ public class OAuth2CodeGrant: OAuth2 {
9494
}
9595

9696
let post = tokenRequest(code)
97-
logIfVerbose("Exchanging code \(code) with redirect \(redirect) for token at \(post.URL.description)")
97+
logIfVerbose("Exchanging code \(code) with redirect \(redirect!) for token at \(post.URL.description)")
9898

9999
// perform the exchange
100-
NSURLConnection.sendAsynchronousRequest(post, queue: NSOperationQueue.mainQueue(), completionHandler: { response, data, error in
100+
let session = NSURLSession.sharedSession()
101+
let task = session.dataTaskWithRequest(post) { data, response, error in
101102
var finalError: NSError?
102103

103104
if nil != error {
@@ -119,37 +120,42 @@ public class OAuth2CodeGrant: OAuth2 {
119120
return
120121
}
121122
}
123+
else {
124+
finalError = genOAuth2Error(http.statusString, .AuthorizationError)
125+
}
122126
}
123127
}
124128

125129
// if we're still here an error must have happened
126130
if nil == finalError {
127-
finalError = genOAuth2Error("Unknown connection error", .NetworkError)
131+
finalError = genOAuth2Error("Unknown connection error for response \(response) with data \(data)", .NetworkError)
128132
}
129133

130134
self.didFail(finalError)
131-
})
135+
}
136+
task.resume()
132137
}
133138

134139

135140
// MARK: - Utilities
136141

137142
/**
138-
* Validates the redirect URI, returns a tuple weth the code and nil on success, nil and an error on failure.
143+
* Validates the redirect URI: returns a tuple with the code and nil on success, nil and an error on failure.
139144
*/
140145
func validateRedirectURL(redirect: NSURL) -> (code: String?, error: NSError?) {
141146
var code: String?
142147
var error: NSError?
143148

144149
let comp = NSURLComponents(URL: redirect, resolvingAgainstBaseURL: true)
145-
if nil != comp.query {
150+
if nil != comp.query && countElements(comp.query!) > 0 {
146151
let query = OAuth2CodeGrant.paramsFromQuery(comp.query!)
147152
if let cd = query["code"] {
148153

149-
// we got a code, check if state is correct
154+
// we got a code, use it if state is correct (and reset state)
150155
if let st = query["state"] {
151156
if st == state {
152157
code = cd
158+
state = ""
153159
}
154160
else {
155161
error = genOAuth2Error("Invalid state \(st), will not use the code", .InvalidState)

OAuth2/extensions.swift

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// Copyright (c) 2014 Pascal Pfiffner. All rights reserved.
77
//
88

9+
import Foundation
10+
911

1012
extension Dictionary {
1113
mutating func addEntries(from: Dictionary) -> Dictionary {
@@ -15,3 +17,11 @@ extension Dictionary {
1517
return self
1618
}
1719
}
20+
21+
extension NSHTTPURLResponse {
22+
public var statusString: String {
23+
get {
24+
return NSHTTPURLResponse.localizedStringForStatusCode(self.statusCode)
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)