Skip to content

Commit

Permalink
Merge pull request #242 from uber/erichg/AuthStrategy
Browse files Browse the repository at this point in the history
auth with Eats
  • Loading branch information
ebgraham authored Sep 7, 2018
2 parents b5f59eb + ed89da8 commit 1a32600
Show file tree
Hide file tree
Showing 29 changed files with 819 additions and 149 deletions.
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1 +1 @@
github "AliSoftware/OHHTTPStubs" "57feceaabf333e72b2c637dfba6c13a7a5c49619"
github "AliSoftware/OHHTTPStubs" "f90c2bb0fb882e43761ab963ca8869d349d2c6e3"
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,23 @@ CLLocation *pickupLocation = [[CLLocation alloc] initWithLatitude: 37.787654 lon
### Native / SSO Authorization
To get access to more informative endpoints, you need to have the end user authorize your application to access their Uber data.
The easiest form of authorization is using the `.native` login type. It allows you to request Privileged scopes and, if your user is logged into the Uber app, it doesn't require your user to enter a username and password. It requires the user to have the native Uber application on their device. The `LoginManager` defaults to using the Native login type, so you simply instantiate a `LoginManager` and call `login()` with your requested scopes.
The easiest form of authorization is using the `.native` login type. It allows you to request Privileged scopes and, if your user is logged into the Uber app, it doesn't require your user to enter a username and password. It requires the user to have the native Uber application on their device.
Native authentication can occur either through the main Uber rides app or through the Uber Eats app. You can also fallback from one app to another, so that for example if the user does not have the UberEats app installed on their device, you can instead authenticate through the main Uber rides app:
```swift
// Swift
let loginManager = LoginManager(loginType: .native, productFlowPriority: [UberAuthenticationProductFlow(.eats), UberAuthenticationProductFlow(.rides)])
```

```objective-c
// Objective-C
UBSDKUberAuthenticationProductFlow *eatsProduct = [[UBSDKUberAuthenticationProductFlow alloc] init:UberProductTypeEats];
UBSDKUberAuthenticationProductFlow *ridesProduct = [[UBSDKUberAuthenticationProductFlow alloc] init:UberProductTypeRides];
UBSDKLoginManager *loginManager = [[UBSDKLoginManager alloc] initWithLoginType:loginType productFlowPriority:@[ eatsProduct, ridesProduct ]];
```
The `LoginManager` defaults to using the Native login type using the main Uber rides app, so you can simply instantiate a `LoginManager` and call `login()` with your requested scopes.
```swift
// Swift
Expand Down
16 changes: 0 additions & 16 deletions examples/Obj-C SDK/Obj-C SDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@
AC0404EB1BFB82CC00AC1501 /* Resources */,
AC0405781BFBB32500AC1501 /* Embed Frameworks */,
15F8745A671B49A0061B3C79 /* [CP] Embed Pods Frameworks */,
507E844BE31547720AE5168A /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -401,21 +400,6 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Obj-C SDK/Pods-Obj-C SDK-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
507E844BE31547720AE5168A /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Obj-C SDK/Pods-Obj-C SDK-resources.sh\"\n";
showEnvVarsInLog = 0;
};
DA2812E3F2C3469BD2EBA6F2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
Expand Down Expand Up @@ -35,6 +45,11 @@
"idiom" : "iphone",
"filename" : "app_icons_dev_sdk_160510_V2_MP_icon180.png",
"scale" : "3x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
Expand Down
3 changes: 2 additions & 1 deletion examples/Obj-C SDK/Obj-C SDK/UBSDKLoginButtonView.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ - (instancetype)initWithFrame:(CGRect)frame scopes:(NSArray<UBSDKScope *> *)scop
self = [super initWithFrame:frame];
if (self) {
_scopes = scopes;
_loginManager = [[UBSDKLoginManager alloc] initWithLoginType:loginType];
UBSDKUberAuthenticationProductFlow *ridesProduct = [[UBSDKUberAuthenticationProductFlow alloc] init:UberProductTypeRides];
_loginManager = [[UBSDKLoginManager alloc] initWithLoginType:loginType productFlowPriority:@[ ridesProduct ]];
_loginButton = ({
UBSDKLoginButton *loginButton = [[UBSDKLoginButton alloc] initWithFrame:CGRectZero scopes:scopes loginManager:_loginManager];
[loginButton sizeToFit];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ - (void)viewDidLoad {
#pragma mark - Private

- (void)_initialSetup {
_loginManager = [[UBSDKLoginManager alloc] initWithLoginType:UBSDKLoginTypeNative];

UBSDKUberAuthenticationProductFlow *ridesProduct = [[UBSDKUberAuthenticationProductFlow alloc] init:UberProductTypeRides];
_loginManager = [[UBSDKLoginManager alloc] initWithLoginType:UBSDKLoginTypeNative productFlowPriority:@[ ridesProduct ]];

NSArray<UBSDKScope *> *scopes = @[UBSDKScope.profile, UBSDKScope.places, UBSDKScope.request];

_blackLoginButton = ({
Expand Down
14 changes: 7 additions & 7 deletions examples/Obj-C SDK/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PODS:
- UberCore (0.9.0)
- UberRides (0.9.0):
- UberCore (0.10.0)
- UberRides (0.10.0):
- UberCore

DEPENDENCIES:
Expand All @@ -9,14 +9,14 @@ DEPENDENCIES:

EXTERNAL SOURCES:
UberCore:
:path: ../../
:path: "../../"
UberRides:
:path: ../../
:path: "../../"

SPEC CHECKSUMS:
UberCore: 89805fdd95ed9d2da27451a48c9375f88fe923a6
UberRides: 90b7d6f60d01f3afa6e797f58f3ccbde824f90bf
UberCore: bbeec9cb7b92de9f292df2f8a345f2e290212746
UberRides: ed61c8d3de1211f0e4b6568d36abc877fdfee2fb

PODFILE CHECKSUM: 245f1d465fbbc4baa291260b541d36e5a0949a0a

COCOAPODS: 1.3.1
COCOAPODS: 1.5.0
14 changes: 7 additions & 7 deletions examples/Swift SDK/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PODS:
- UberCore (0.8.0)
- UberRides (0.8.0):
- UberCore (0.10.0)
- UberRides (0.10.0):
- UberCore

DEPENDENCIES:
Expand All @@ -9,14 +9,14 @@ DEPENDENCIES:

EXTERNAL SOURCES:
UberCore:
:path: ../../
:path: "../../"
UberRides:
:path: ../../
:path: "../../"

SPEC CHECKSUMS:
UberCore: f21a609068491e3f04de92edf82dce4ed7a215e9
UberRides: 026be2ddb0f190e9b5eada1c273069eabd6f708b
UberCore: bbeec9cb7b92de9f292df2f8a345f2e290212746
UberRides: ed61c8d3de1211f0e4b6568d36abc877fdfee2fb

PODFILE CHECKSUM: 1d713d30b94c4238ccc4571330ddf2a95fe4daf5

COCOAPODS: 1.3.1
COCOAPODS: 1.5.0
16 changes: 0 additions & 16 deletions examples/Swift SDK/Swift SDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@
AC0404A21BFAD0C800AC1501 /* Resources */,
DCEB80851D078BB500899810 /* Embed Frameworks */,
E6835DE2B81B6684590AD161 /* [CP] Embed Pods Frameworks */,
8B1F36539338433F86C28295 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -323,21 +322,6 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
8B1F36539338433F86C28295 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Swift SDK/Pods-Swift SDK-resources.sh\"\n";
showEnvVarsInLog = 0;
};
B93972D24501F42E9C68E979 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//
// AuthenticationProvider.swift
// UberRides
//
// Copyright © 2018 Uber Technologies, Inc. All rights reserved.
//
// 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 CONN

import Foundation

/**
* Builder for the given loginType's applicable UberAuthenticators.
*/
class AuthenticationProvider {

let productFlowPriority: [UberAuthenticationProductFlow]
let scopes: [UberScope]

/// Returns an AuthenticationProvider.
///
/// - Parameters:
/// - scopes: The access scopes for authentication.
/// - productFlowPriority: The product flows against which to authenticate, in the order of which Uber products you'd like to use to authenticate the user.
///
/// For example, you may want to SSO with the UberEats app, but if the app does not exist on the user's device, then try to authenticate with the Uber Rides app instead. In this example you'd call this parameter with [ eats, rides ].
init(scopes: [UberScope], productFlowPriority: [UberAuthenticationProductFlow]) {
self.scopes = scopes
self.productFlowPriority = productFlowPriority
}

/// Returns the ordered list of authenticators to use for the given login type.
func authenticators(for loginType: LoginType) -> [ UberAuthenticating ] {
return productFlowPriority.map { (authProduct: UberAuthenticationProductFlow) in
uberAuthenticator(loginType: loginType, authProduct: authProduct)
}
}

private func uberAuthenticator(loginType: LoginType, authProduct: UberAuthenticationProductFlow) -> UberAuthenticating {
switch loginType {
case .authorizationCode:
// Rides and Eats temporarily share the same authorization code flow
return AuthorizationCodeGrantAuthenticator(scopes: scopes)
case .implicit:
// Rides and Eats temporarily share the same implicit grant code flow
return ImplicitGrantAuthenticator(scopes: scopes)
case .native:
switch authProduct.uberProductType {
case .rides:
return RidesNativeAuthenticator(scopes: scopes)
case .eats:
return EatsNativeAuthenticator(scopes: scopes)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ import UIKit
let accessToken = try AccessTokenFactory.createAccessToken(fromRedirectURL: url)

completion?(accessToken, nil)
} catch let ridesError as NSError {
completion?(nil, ridesError)
} catch let error as NSError {
completion?(nil, error)
} catch {
completion?(nil, UberAuthenticationErrorFactory.errorForType(ridesAuthenticationErrorType: .invalidResponse))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// EatsAuthenticationDeeplink.swift
// UberRides
//
// Copyright © 2018 Uber Technologies, Inc. All rights reserved.
//
// 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

/**
* A Deeplinking object for authenticating a user via the native UberEats food delivery app
*/
@objc(UBSDKEatsAuthenticationDeeplink) public class EatsAuthenticationDeeplink: BaseDeeplink {

/**
Initializes an Authentication Deeplink to request the provided scopes

- parameter scopes: An array of UberScopes you would like to request

- returns: An initialized AuthenticationDeeplink
*/
@objc public init(scopes: [UberScope]) {
let queryItems = AuthenticationURLUtility.buildQueryParameters(scopes)
let scheme = "eatsauth"
let domain = "connect"

super.init(scheme: scheme, host: domain, path: "", queryItems: queryItems)!
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// EatsNativeAuthenticator.swift
// UberRides
//
// Copyright © 2018 Uber Technologies, Inc. All rights reserved.
//
// 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

/**
* UberAuthenticating object for authenticating a user via the native UberEats food delivery app
*/
@objc(UBSSOEatsNativeAuthenticator) public class EatsNativeAuthenticator: BaseAuthenticator {
private var deeplink: EatsAuthenticationDeeplink

@objc override var authorizationURL: URL {
return deeplink.url
}

/**
Creates a NativeAuthenticator using the provided scopes

- parameter request: the URL request.

- returns: true if a redirect was handled, false otherwise.
*/
@objc public override init(scopes: [UberScope]) {
deeplink = EatsAuthenticationDeeplink(scopes: scopes)
super.init(scopes: scopes)
}
}
Loading

0 comments on commit 1a32600

Please sign in to comment.