Skip to content

Commit

Permalink
Rename oidc conformant userInfo
Browse files Browse the repository at this point in the history
Tests - Added OIDC userInfo
  • Loading branch information
cocojoe committed Jun 13, 2017
1 parent b326c74 commit cf653b9
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 27 deletions.
1 change: 0 additions & 1 deletion App/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class ViewController: UIViewController {
}

@IBAction func startOAuth2(_ sender: Any) {
print(UserInfo.publicClaims)
var auth0 = Auth0.webAuth()
auth0
.logging(enabled: true)
Expand Down
10 changes: 10 additions & 0 deletions Auth0.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
5B059B591EF0223A00D4DB9A /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B059B581EF0223A00D4DB9A /* Date.swift */; };
5B059B5A1EF0223A00D4DB9A /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B059B581EF0223A00D4DB9A /* Date.swift */; };
5B059B5B1EF0223A00D4DB9A /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B059B581EF0223A00D4DB9A /* Date.swift */; };
5B059B5C1EF0223A00D4DB9A /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B059B581EF0223A00D4DB9A /* Date.swift */; };
5B25A52F1E3F520300563AE5 /* NativeAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B25A52E1E3F520300563AE5 /* NativeAuth.swift */; };
5B25A5331E3F68FA00563AE5 /* SafariSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B25A5321E3F68FA00563AE5 /* SafariSession.swift */; };
5B2860CE1EEAC30500C75D54 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2860CD1EEAC30500C75D54 /* UserInfo.swift */; };
Expand Down Expand Up @@ -298,6 +302,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
5B059B581EF0223A00D4DB9A /* Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
5B25A52E1E3F520300563AE5 /* NativeAuth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NativeAuth.swift; path = Auth0/NativeAuth.swift; sourceTree = SOURCE_ROOT; };
5B25A5321E3F68FA00563AE5 /* SafariSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SafariSession.swift; path = Auth0/SafariSession.swift; sourceTree = SOURCE_ROOT; };
5B2860CD1EEAC30500C75D54 /* UserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -497,6 +502,7 @@
5BEDE1581EC1FFE40007300D /* Utils */ = {
isa = PBXGroup;
children = (
5B059B581EF0223A00D4DB9A /* Date.swift */,
5BEDE1891EC21B040007300D /* CredentialsManager.swift */,
5B5E93F81EC45C22002A37F9 /* CredentialsManagerError.swift */,
);
Expand Down Expand Up @@ -1297,6 +1303,7 @@
5F53F5CE1CFD157300476A46 /* AuthTransaction.swift in Sources */,
5FF465BC1CE2AC4500F7ED8C /* Management.swift in Sources */,
5F4A1F961D00AABC00C72242 /* OAuth2Grant.swift in Sources */,
5B059B591EF0223A00D4DB9A /* Date.swift in Sources */,
5FCAB1731D09009600331C84 /* NSData+URLSafe.swift in Sources */,
5FD255BA1D14F70B00387ECB /* WebAuthError.swift in Sources */,
5B25A52F1E3F520300563AE5 /* NativeAuth.swift in Sources */,
Expand Down Expand Up @@ -1337,6 +1344,7 @@
5FDE876A1D8A424700EA27DC /* Credentials.swift in Sources */,
5FCCC31D1CF51DF300901E2E /* _ObjectiveManagementAPI.swift in Sources */,
5F28B4621D8216180000EB23 /* Loggable.swift in Sources */,
5B059B5A1EF0223A00D4DB9A /* Date.swift in Sources */,
5F6FAC641D09E98000D5B4EA /* Logger.swift in Sources */,
5FF465BD1CE2AC4500F7ED8C /* Management.swift in Sources */,
5F23E6EF1D4B872000C3F2D9 /* A0ChallengeGenerator.m in Sources */,
Expand Down Expand Up @@ -1447,6 +1455,7 @@
5F23E6E61D4ACD8500C3F2D9 /* Requestable.swift in Sources */,
5FDE87671D8A424700EA27DC /* Profile.swift in Sources */,
5FDE875F1D8A424700EA27DC /* AuthenticationError.swift in Sources */,
5B059B5B1EF0223A00D4DB9A /* Date.swift in Sources */,
5F23E6E31D4ACD7F00C3F2D9 /* ManagementError.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1480,6 +1489,7 @@
5F23E70F1D4B88FC00C3F2D9 /* Requestable.swift in Sources */,
5FDE87681D8A424700EA27DC /* Profile.swift in Sources */,
5FDE87601D8A424700EA27DC /* AuthenticationError.swift in Sources */,
5B059B5C1EF0223A00D4DB9A /* Date.swift in Sources */,
5F23E70C1D4B88F600C3F2D9 /* ManagementError.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
4 changes: 2 additions & 2 deletions Auth0/Auth0Authentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ struct Auth0Authentication: Authentication {
return Request(session: session, url: userInfo, method: "GET", handle: authenticationObject, headers: ["Authorization": "Bearer \(token)"], logger: self.logger, telemetry: self.telemetry)
}

func userClaimInfo(token: String) -> Request<UserInfo, AuthenticationError> {
func userInfo(withAccessToken accessToken: String) -> Request<UserInfo, AuthenticationError> {
let userInfo = URL(string: "/userinfo", relativeTo: self.url)!
return Request(session: session, url: userInfo, method: "GET", handle: authenticationObject, headers: ["Authorization": "Bearer \(token)"], logger: self.logger, telemetry: self.telemetry)
return Request(session: session, url: userInfo, method: "GET", handle: authenticationObject, headers: ["Authorization": "Bearer \(accessToken)"], logger: self.logger, telemetry: self.telemetry)
}

func loginSocial(token: String, connection: String, scope: String, parameters: [String: Any]) -> Request<Credentials, AuthenticationError> {
Expand Down
6 changes: 3 additions & 3 deletions Auth0/Authentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,16 +322,16 @@ public protocol Authentication: Trackable, Loggable {
```
Auth0
.authentication(clientId, domain: "samples.auth0.com")
.userClaimInfo(token: token)
.userInfo(withAccessToken: accessToken)
.start { print($0) }
```

- parameter token: token obtained by authenticating the user
- parameter accessToken: accessToken obtained by authenticating the user

- returns: a request that will yield user information
- important: This method should be used for OIDC Conformant clients.
*/
func userClaimInfo(token: String) -> Request<UserInfo, AuthenticationError>
func userInfo(withAccessToken accessToken: String) -> Request<UserInfo, AuthenticationError>

/**
Logs in a user using a social Identity Provider token. e.g. Facebook
Expand Down
34 changes: 34 additions & 0 deletions Auth0/Date.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Date.swift
//
// Copyright (c) 2017 Auth0 (http://auth0.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Foundation

func date(from string: String) -> Date? {
guard let interval = Double(string) else {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = TimeZone(identifier: "UTC")
return formatter.date(from: string)
}
return Date(timeIntervalSince1970: interval)
}
11 changes: 0 additions & 11 deletions Auth0/Profile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,3 @@ public class Profile: NSObject, JSONObjectPayload {
}

}

func date(from string: String) -> Date? {
guard let interval = Double(string) else {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = TimeZone(identifier: "UTC")
return formatter.date(from: string)
}
return Date(timeIntervalSince1970: interval)
}
27 changes: 26 additions & 1 deletion Auth0Tests/AuthenticationSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ class AuthenticationSpec: QuickSpec {
}

describe("user information") {

it("should return token information") {
stub(condition: isTokenInfo(Domain) && hasAllOf(["id_token": IdToken])) { _ in return tokenInfo() }.name = "token info"
waitUntil(timeout: Timeout) { done in
Expand All @@ -582,7 +583,7 @@ class AuthenticationSpec: QuickSpec {
}

it("should return user information") {
stub(condition: isUserInfo(Domain) && hasBearerToken(AccessToken)) { _ in return userInfo() }.name = "user info"
stub(condition: isUserInfo(Domain) && hasBearerToken(AccessToken)) { _ in return userInfo(withProfile: basicProfile()) }.name = "user info"
waitUntil(timeout: Timeout) { done in
auth.userInfo(token: AccessToken).start { result in
expect(result).to(haveProfile(UserId))
Expand All @@ -603,6 +604,30 @@ class AuthenticationSpec: QuickSpec {

}

describe("user information OIDC conformant") {

it("should return user information") {
stub(condition: isUserInfo(Domain) && hasBearerToken(AccessToken)) { _ in return userInfo(withProfile: basicProfileOIDC()) }.name = "user info oidc"
waitUntil(timeout: Timeout) { done in
auth.userInfo(withAccessToken: AccessToken).start { result in
expect(result).to(haveProfileOIDC(Sub))
done()
}
}
}

it("should report failure to get user info") {
stub(condition: isUserInfo(Domain)) { _ in return authFailure(error: "invalid_token", description: "the token is invalid") }.name = "token info failed"
waitUntil(timeout: Timeout) { done in
auth.userInfo(withAccessToken: AccessToken).start { result in
expect(result).to(haveAuthenticationError(code: "invalid_token", description: "the token is invalid"))
done()
}
}
}

}

describe("social login") {

beforeEach {
Expand Down
9 changes: 9 additions & 0 deletions Auth0Tests/Matchers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,15 @@ func haveProfile(_ userId: String) -> Predicate<Result<Profile>> {
}
}

func haveProfileOIDC(_ sub: String) -> Predicate<Result<UserInfo>> {
return Predicate<Result<UserInfo>>.define("have userInfo for sub: <\(sub)>") { expression, failureMessage -> PredicateResult in
if let actual = try expression.evaluate(), case .success(let userInfo) = actual {
return PredicateResult(bool: userInfo.sub == sub, message: failureMessage)
}
return PredicateResult(status: .doesNotMatch, message: failureMessage)
}
}

func haveObjectWithAttributes(_ attributes: [String]) -> Predicate<Result<[String: Any]>> {
return Predicate<Result<[String: Any]>>.define("have attribues \(attributes)") { expression, failureMessage -> PredicateResult in
if let actual = try expression.evaluate(), case .success(let value) = actual {
Expand Down
2 changes: 1 addition & 1 deletion Auth0Tests/ProfileSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class UserProfileSpec: QuickSpec {
}

it("should build with required OIDC conformant values") {
let profile = Profile(json: basicOIDCProfile())
let profile = Profile(json: basicProfileOIDC())
expect(profile).toNot(beNil())
expect(profile?.id) == Sub
expect(profile?.name) == Support
Expand Down
8 changes: 4 additions & 4 deletions Auth0Tests/Responses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ func passwordless(_ email: String, verified: Bool) -> OHHTTPStubsResponse {
}

func tokenInfo() -> OHHTTPStubsResponse {
return userInfo()
return userInfo(withProfile: basicProfile())
}

func userInfo() -> OHHTTPStubsResponse {
return OHHTTPStubsResponse(jsonObject: basicProfile(), statusCode: 200, headers: nil)
func userInfo(withProfile profile: [String: Any]) -> OHHTTPStubsResponse {
return OHHTTPStubsResponse(jsonObject: profile, statusCode: 200, headers: nil)
}

func basicProfile(_ id: String = UserId, name: String = Support, nickname: String = Nickname, picture: String = PictureURL.absoluteString, createdAt: String = CreatedAtUnix) -> [String: Any] {
return ["user_id": id, "name": name, "nickname": nickname, "picture": picture, "created_at": createdAt]
}

func basicOIDCProfile(_ sub: String = Sub, name: String = Support, nickname: String = Nickname, picture: String = PictureURL.absoluteString, updatedAt: String = UpdatedAtUnix) -> [String: Any] {
func basicProfileOIDC(_ sub: String = Sub, name: String = Support, nickname: String = Nickname, picture: String = PictureURL.absoluteString, updatedAt: String = UpdatedAtUnix) -> [String: Any] {
return ["sub": sub, "name": name, "nickname": nickname, "picture": picture, "updated_at": updatedAt]
}
func managementResponse(_ payload: Any) -> OHHTTPStubsResponse {
Expand Down
8 changes: 4 additions & 4 deletions Auth0Tests/UserInfoSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class UserInfoSpec: QuickSpec {
}

it("should build with basic oidc profile") {
let userInfo = UserInfo(json: basicOIDCProfile())
let userInfo = UserInfo(json: basicProfileOIDC())
expect(userInfo?.sub) == Sub
expect(userInfo?.name) == Support
expect(userInfo?.nickname) == Nickname
Expand All @@ -75,7 +75,7 @@ class UserInfoSpec: QuickSpec {
}

it("should build with extended oidc profile") {
var info = basicOIDCProfile()
var info = basicProfileOIDC()
let optional: [String: Any] = [
"website": WebsiteURL.absoluteString,
"profile": ProfileURL.absoluteString,
Expand All @@ -98,7 +98,7 @@ class UserInfoSpec: QuickSpec {
}

it("should build with basic oidc profile with locale and zoneinfo") {
var info = basicOIDCProfile()
var info = basicProfileOIDC()
let optional: [String: Any] = [
"locale": LocaleUS,
"zoneinfo": ZoneEST
Expand All @@ -114,7 +114,7 @@ class UserInfoSpec: QuickSpec {
describe("custom claims") {

it("should build with basic profile and two custom claims") {
var info = basicOIDCProfile()
var info = basicProfileOIDC()
let optional: [String: Any] = [
"user_list": "user1",
"user_active": true
Expand Down

0 comments on commit cf653b9

Please sign in to comment.