Skip to content

Commit

Permalink
Move all extra auth parameters to authConfig
Browse files Browse the repository at this point in the history
This commit addresses the discrepancy introduced by the last merge.
  • Loading branch information
p2 committed Nov 24, 2016
1 parent ef7a77c commit 068cf29
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 53 deletions.
12 changes: 9 additions & 3 deletions OAuth2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0810;
ORGANIZATIONNAME = "Pascal Pfiffner";
TargetAttributes = {
659854451C5B3BEA00237D39 = {
Expand Down Expand Up @@ -787,6 +787,7 @@
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
Expand All @@ -812,6 +813,7 @@
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
Expand Down Expand Up @@ -848,8 +850,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -898,8 +902,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -932,7 +938,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -954,7 +960,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand Down
2 changes: 1 addition & 1 deletion OAuth2.xcodeproj/xcshareddata/xcschemes/OAuth2iOS.xcscheme
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ Some sites also want the client-id/secret combination in the request _body_, not
Sometimes you also need to provide additional authorization parameters.
This can be done in 3 ways:

oauth2.clientConfig.authParameters = ["duration": "permanent"]
oauth2.authParameters = ["duration": "permanent"]
// or in your settings:
"parameters": ["duration": "permanent"]
// or when you authorize manually:
Expand Down
44 changes: 24 additions & 20 deletions Sources/Base/OAuth2Base.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ open class OAuth2Base: OAuth2Securable {
get { return clientConfig.accessToken }
set { clientConfig.accessToken = newValue }
}
/// The receiver's id token.
open var idToken: String? {
get { return clientConfig.idToken }
Expand All @@ -116,8 +116,8 @@ open class OAuth2Base: OAuth2Securable {

/// Custom authorization parameters.
public var authParameters: OAuth2StringDict? {
get { return clientConfig.authParameters }
set { clientConfig.authParameters = newValue }
get { return authConfig.customParameters }
set { authConfig.customParameters = newValue }
}


Expand Down Expand Up @@ -158,23 +158,24 @@ open class OAuth2Base: OAuth2Securable {

The following settings keys are currently supported:

- client_id (string)
- client_secret (string), usually only needed for code grant
- authorize_uri (URL-string)
- token_uri (URL-string), if omitted the authorize_uri will be used to obtain tokens
- redirect_uris (list of URL-strings)
- scope (string)

- client_name (string)
- registration_uri (URL-string)
- logo_uri (URL-string)

- keychain (bool, true by default, applies to using the system keychain)
- keychain_access_mode (string, value for keychain kSecAttrAccessible attribute, kSecAttrAccessibleWhenUnlocked by default)
- keychain_access_group (string, value for keychain kSecAttrAccessGroup attribute, nil by default)
- verbose (bool, false by default, applies to client logging)
- secret_in_body (bool, false by default, forces the flow to use the request body for the client secret)
- token_assume_unexpired (bool, true by default, whether to use access tokens that do not come with an "expires_in" parameter)
- client_id (String)
- client_secret (String), usually only needed for code grant
- authorize_uri (URL-String)
- token_uri (URL-String), if omitted the authorize_uri will be used to obtain tokens
- redirect_uris (Array of URL-Strings)
- scope (String)

- client_name (String)
- registration_uri (URL-String)
- logo_uri (URL-String)

- keychain (Bool, true by default, applies to using the system keychain)
- keychain_access_mode (String, value for keychain kSecAttrAccessible attribute, kSecAttrAccessibleWhenUnlocked by default)
- keychain_access_group (String, value for keychain kSecAttrAccessGroup attribute, nil by default)
- verbose (Bool, false by default, applies to client logging)
- secret_in_body (Bool, false by default, forces the flow to use the request body for the client secret)
- parameters ([String: String], custom request parameters to be added during authorization)
- token_assume_unexpired (Bool, true by default, whether to use access tokens that do not come with an "expires_in" parameter)
*/
override public init(settings: OAuth2JSON) {
clientConfig = OAuth2ClientConfig(settings: settings)
Expand All @@ -183,6 +184,9 @@ open class OAuth2Base: OAuth2Securable {
if let inBody = settings["secret_in_body"] as? Bool {
authConfig.secretInBody = inBody
}
if let params = settings["parameters"] as? OAuth2StringDict {
authConfig.customParameters = params
}
if let ttl = settings["title"] as? String {
authConfig.ui.title = ttl
}
Expand Down
15 changes: 4 additions & 11 deletions Sources/Base/OAuth2ClientConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,16 @@ open class OAuth2ClientConfig {
/// Contains special authorization request headers, can be used to override defaults.
open var authHeaders: OAuth2Headers?

/// Custom request parameters to be added during authorization.
open var authParameters: OAuth2StringDict?

/// There's an issue with authenticating through 'system browser', where safari says:
/// "Safari cannot open the page because the address is invalid." if you first selects 'Cancel'
/// when asked to switch back to "your" app, and then you try authenticating again.
/// To get rid of it you must restart Safari.
/// "Safari cannot open the page because the address is invalid." if you first selects 'Cancel' when asked to switch back to "your" app,
/// and then you try authenticating again. To get rid of it you must restart Safari.
///
/// Read more about it here:
/// http://stackoverflow.com/questions/27739442/ios-safari-does-not-recognize-url-schemes-after-user-cancels
/// https://community.fitbit.com/t5/Web-API/oAuth2-authentication-page-gives-me-a-quot-Cannot-Open-Page-quot-error/td-p/1150391
///
/// Toggling `safariCancelWorkaround` to true will send an extra get-paramter to make the url unique,
/// thus it will ask again for the new url.
/// Toggling `safariCancelWorkaround` to true will send an extra get-paramter to make the url unique, thus it will ask again for the new
/// url.
open var safariCancelWorkaround = false

/**
Expand Down Expand Up @@ -123,9 +119,6 @@ open class OAuth2ClientConfig {
if let headers = settings["headers"] as? OAuth2Headers {
authHeaders = headers
}
if let params = settings["parameters"] as? OAuth2StringDict {
authParameters = params
}

// access token options
if let assume = settings["token_assume_unexpired"] as? Bool {
Expand Down
21 changes: 8 additions & 13 deletions Sources/Flows/OAuth2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,18 @@ open class OAuth2: OAuth2Base {
be attempted and if it success, an access token will be requested.

- parameter params: Optional key/value pairs to pass during authorization and token refresh
- parameter callback: The callback to call when authorization finishes (parameters will be non-nil but may be an empty dict), fails or is
cancelled (error will be non-nil, e.g. `.requestCancelled` if auth was aborted)
- parameter callback: The callback to call when authorization finishes (parameters will be non-nil but may be an empty dict), fails or
is cancelled (error will be non-nil, e.g. `.requestCancelled` if auth was aborted)
*/
public final func authorize(params: OAuth2StringDict? = nil, callback: @escaping ((OAuth2JSON?, OAuth2Error?) -> Void)) {
if isAuthorizing {
callback(nil, OAuth2Error.alreadyAuthorizing)
return
}
var prms = authParameters
if nil != prms, let params = params {
params.forEach() { prms![$0] = $1 }
}
let useParams = prms ?? params

didAuthorizeOrFail = callback
logger?.debug("OAuth2", msg: "Starting authorization")
tryToObtainAccessTokenIfNeeded(params: useParams) { successParams in
tryToObtainAccessTokenIfNeeded(params: params) { successParams in
if let successParams = successParams {
self.didAuthorize(withParameters: successParams)
}
Expand All @@ -114,7 +109,7 @@ open class OAuth2: OAuth2Base {
else {
do {
assert(Thread.isMainThread)
try self.doAuthorize(params: useParams)
try self.doAuthorize(params: params)
}
catch let error {
self.didFail(with: error.asOAuth2Error)
Expand Down Expand Up @@ -143,8 +138,8 @@ open class OAuth2: OAuth2Base {

- parameter from: The context to start authorization from, depends on platform (UIViewController or NSWindow, see `authorizeContext`)
- parameter params: Optional key/value pairs to pass during authorization
- parameter callback: The callback to call when authorization finishes (parameters will be non-nil but may be an empty dict), fails or is
cancelled (error will be non-nil, e.g. `.requestCancelled` if auth was aborted)
- parameter callback: The callback to call when authorization finishes (parameters will be non-nil but may be an empty dict), fails or
is cancelled (error will be non-nil, e.g. `.requestCancelled` if auth was aborted)
*/
open func authorizeEmbedded(from context: AnyObject, params: OAuth2StringDict? = nil, callback: @escaping ((_ authParameters: OAuth2JSON?, _ error: OAuth2Error?) -> Void)) {
if isAuthorizing { // `authorize()` will check this, but we want to exit before changing `authConfig`
Expand Down Expand Up @@ -268,7 +263,7 @@ open class OAuth2: OAuth2Base {
Method that creates the OAuth2AuthRequest instance used to create the authorize URL

- parameter redirect: The redirect URI string to supply. If it is nil, the first value of the settings' `redirect_uris` entries is
used. Must be present in the end!
used. Must be present in the end!
- parameter scope: The scope to request
- parameter params: Any additional parameters as dictionary with string keys and values that will be added to the query part
- returns: OAuth2AuthRequest to be used to call to the authorize endpoint
Expand Down Expand Up @@ -310,7 +305,7 @@ open class OAuth2: OAuth2Base {
Convenience method to be overridden by and used from subclasses.

- parameter redirect: The redirect URI string to supply. If it is nil, the first value of the settings' `redirect_uris` entries is
used. Must be present in the end!
used. Must be present in the end!
- parameter scope: The scope to request
- parameter params: Any additional parameters as dictionary with string keys and values that will be added to the query part
- returns: NSURL to be used to start the OAuth dance
Expand Down
25 changes: 23 additions & 2 deletions Tests/FlowTests/OAuth2CodeGrantTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,29 @@ class OAuth2CodeGrantTests: XCTestCase {
let req2 = try! oauth.accessTokenRequest(with: "pp").asURLRequest(for: oauth)
let body2 = String(data: req2.httpBody!, encoding: String.Encoding.utf8)
let query2 = OAuth2CodeGrant.params(fromQuery: body2!)
XCTAssertEqual(query2["foo"]!, "bar", "Expecting key `foo` to be `bar`")
}
XCTAssertEqual(query2["foo"], "bar", "Expecting key `foo` to be `bar`")

oauth.authParameters = ["bar": "hat"]

// in body
let req3 = try! oauth.accessTokenRequest(with: "pp").asURLRequest(for: oauth)
let body3 = String(data: req3.httpBody!, encoding: String.Encoding.utf8)
let query3 = OAuth2CodeGrant.params(fromQuery: body3!)
XCTAssertEqual(query3["bar"], "hat", "Expecting key `bar` to be `hat`")
}

func testCustomAuthParametersInit() {
var settings = baseSettings
settings["parameters"] = ["foo": "bar"]
let oauth = OAuth2CodeGrant(settings: settings)
oauth.redirect = "oauth2://callback"
oauth.context.redirectURL = "oauth2://callback"

let req = try! oauth.accessTokenRequest(with: "pp").asURLRequest(for: oauth)
let body = String(data: req.httpBody!, encoding: String.Encoding.utf8)
let query = OAuth2CodeGrant.params(fromQuery: body!)
XCTAssertEqual(query["foo"], "bar", "Expecting key `foo` to be `bar`")
}

func testTokenRequestAgainstAuthURL() {

Expand Down

0 comments on commit 068cf29

Please sign in to comment.