Skip to content

Commit

Permalink
Add support for extended profile using SIWA token exchange (#322)
Browse files Browse the repository at this point in the history
* Add support for extended profile using SIWA token exchange

* Fix indenting/whitespace

* Revert accidental Cartfile.resolved changes

* Reorder SIWA parameters, and stop sending missing values

* Expand test cases for SIWA
  • Loading branch information
asmclean authored and cocojoe committed Nov 13, 2019
1 parent 97952b2 commit 5e6a256
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
30 changes: 24 additions & 6 deletions Auth0/Authentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -911,21 +911,39 @@ public extension Authentication {
```
Auth0
.authentication(clientId: clientId, domain: "samples.auth0.com")
.tokenExchange(withAppleAuthorizationCode: authCode, scope: "openid profile offline_access", audience: "https://myapi.com/api)
.tokenExchange(withAppleAuthorizationCode: authCode, scope: "openid profile offline_access", audience: "https://myapi.com/api, fullName: credentials.fullName)
.start { print($0) }
```

- parameter authCode: Authorization Code retrieved from Apple Authorization
- parameter scope: requested scope value when authenticating the user. By default is 'openid profile offline_access'
- parameter audience: API Identifier that the client is requesting access to
- parameter fullName: The full name property returned with the Apple ID Credentials

- returns: a request that will yield Auth0 user's credentials
*/
func tokenExchange(withAppleAuthorizationCode authCode: String, scope: String? = nil, audience: String? = nil) -> Request<Credentials, AuthenticationError> {
var parameters = [ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": authCode,
"subject_token_type": "http://auth0.com/oauth/token-type/apple-authz-code",
"scope": scope ?? "openid profile offline_access"]
func tokenExchange(withAppleAuthorizationCode authCode: String, scope: String? = nil, audience: String? = nil, fullName: PersonNameComponents? = nil) -> Request<Credentials, AuthenticationError> {
var parameters: [String: String] =
[ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": authCode,
"subject_token_type": "http://auth0.com/oauth/token-type/apple-authz-code",
"scope": scope ?? "openid profile offline_access" ]
if let fullName = fullName {
let name = [
"firstName": fullName.givenName,
"lastName": fullName.familyName
].filter { $0.value != nil }.mapValues { $0! }
if !name.isEmpty, let jsonData = try? String(
data: JSONSerialization.data(
withJSONObject: [
"name": name
],
options: []),
encoding: String.Encoding.utf8
) {
parameters["user_profile"] = jsonData
}
}
parameters["audience"] = audience
return self.tokenExchange(withParameters: parameters)
}
Expand Down
72 changes: 71 additions & 1 deletion Auth0Tests/AuthenticationSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,28 @@ class AuthenticationSpec: QuickSpec {
"scope": "openid email",
"audience": "https://myapi.com/api"
])) { _ in return authResponse(accessToken: AccessToken, idToken: IdToken) }.name = "Token Exchange Apple Success with custom scope and audience"

stub(condition: isToken(Domain) && hasAtLeast([
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "VALIDNAMECODE",
"subject_token_type": "http://auth0.com/oauth/token-type/apple-authz-code"]) &&
(hasAtLeast(["user_profile": "{\"name\":{\"lastName\":\"Smith\",\"firstName\":\"John\"}}" ]) || hasAtLeast(["user_profile": "{\"name\":{\"firstName\":\"John\",\"lastName\":\"Smith\"}}" ]))
) { _ in return authResponse(accessToken: AccessToken, idToken: IdToken) }.name = "Token Exchange Apple Success with user profile"

stub(condition: isToken(Domain) && hasAtLeast([
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "VALIDPARTIALNAMECODE",
"subject_token_type": "http://auth0.com/oauth/token-type/apple-authz-code",
"user_profile": "{\"name\":{\"firstName\":\"John\"}}"
])) { _ in return authResponse(accessToken: AccessToken, idToken: IdToken) }.name = "Token Exchange Apple Success with partial user profile"

stub(condition: isToken(Domain) && hasAtLeast([
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "VALIDMISSINGNAMECODE",
"subject_token_type": "http://auth0.com/oauth/token-type/apple-authz-code"]) &&
hasNoneOf(["user_profile"])
) { _ in return authResponse(accessToken: AccessToken, idToken: IdToken) }.name = "Token Exchange Apple Success with missing user profile"

}

it("should exchange apple auth code for credentials") {
Expand Down Expand Up @@ -284,8 +306,56 @@ class AuthenticationSpec: QuickSpec {
}
}

}
it("should exchange apple auth code for credentials with fullName") {
var fullName = PersonNameComponents()
fullName.givenName = "John"
fullName.familyName = "Smith"
fullName.middleName = "Ignored"

waitUntil(timeout: Timeout) { done in
auth.tokenExchange(withAppleAuthorizationCode: "VALIDNAMECODE",
fullName: fullName)
.start { result in
expect(result).to(haveCredentials())
done()
}
}
}

it("should exchange apple auth code for credentials with partial fullName") {
var fullName = PersonNameComponents()
fullName.givenName = "John"
fullName.familyName = nil
fullName.middleName = "Ignored"

waitUntil(timeout: Timeout) { done in
auth.tokenExchange(withAppleAuthorizationCode: "VALIDPARTIALNAMECODE",
fullName: fullName)
.start { result in
expect(result).to(haveCredentials())
done()
}
}
}

it("should exchange apple auth code for credentials with missing fullName") {
var fullName = PersonNameComponents()
fullName.givenName = nil
fullName.familyName = nil
fullName.middleName = nil

waitUntil(timeout: Timeout) { done in
auth.tokenExchange(withAppleAuthorizationCode: "VALIDMISSINGNAMECODE",
fullName: fullName)
.start { result in
expect(result).to(haveCredentials())
done()
}
}
}

}

describe("revoke refresh token") {

let refreshToken = UUID().uuidString.replacingOccurrences(of: "-", with: "")
Expand Down

0 comments on commit 5e6a256

Please sign in to comment.