Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for extended profile using SIWA token exchange #322

Merged
merged 6 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
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
26 changes: 25 additions & 1 deletion Auth0Tests/AuthenticationSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@ 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"

}

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

}
it("should exchange apple auth code for credentials with fullName") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are there any cases it will fail e.g. if first name is missing or last name is missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there are not. The values can be missing or null and it won't cause any issues. Now, I've filtered them out if there is no value.

var fullName = PersonNameComponents()
fullName.givenName = "John"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add test cases for when the name and/or surname are nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

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()
}
}
}

}

describe("revoke refresh token") {

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