The following is an example of implementing login and registering a user using a JSON Web Token (JWT).

Implementation Steps:

  1. Implement VOAuthClient.
  2. Create a JWT Token.
  3. Create a VOCredential with the JWT Token.
  4. Call login on VOEngine’s VOUserManager with the VOCredential.

Sample Code:

#import <UIKit/UIKit.h>
#import <VouchrSDK/VouchrSDK.h>

@interface VouchrSDKLoginManager () <VOAuthClient>

@property (nonatomic) VOEngine *vouchrSDK;
@property (nonatomic) VOCredential *credential;
@property (nonatomic) NSString *username;

@end

@implementation VouchrSDKLoginManager

- (void)loginWithViewController:(UIViewController *)viewController
                   onCompletion:(void(^)(VOUser *user, NSError *error))completion {
    NSString *username = @"someusername";
    NSString *password = @"somepassword";
        [self loginToVouchrSDKWithUsername:username password:password onCompletion:completion];
}

- (void)loginToVouchrSDKWithUsername:(NSString *)username password:(NSString *)password onCompletion:(void(^)(VOUser *user, NSError *error))completion {
    self.username = username;
    
    // Step 2
    NSString *jwtToken = [self createJWTTokenFromUsername:username password:password];
    
    // Step 3
    self.credential = [VOCredential credentialWithDictionary:@{@"networkId": username,
                                                               @"network": self.networkName,
                                                               @"idToken": jwtToken}];
    // Step 4
    [self.vouchrSDK.userManager loginWithCredentials:self.credential authClient:self onSuccess:^(VOUser *user) {
        if (completion) completion(user, nil);
    } onError:^(NSError * _Nonnull error) {
        if (completion) completion(nil, error);
    }];
}

// Step 1
- (void)userForRegistrationWithCredential:(VOCredential *)credential onSuccess:(void (^)(VOCredential *credential, VOSimpleUser *user))onSuccess onError:(void (^)(NSError *))onError {
    onSuccess(credential, [VOSimpleUser simpleUserWithFirstName:@"test" lastName:@"user" email:self.username profileImageUrl:nil birthday:nil]);
}

// CRITICAL: for production uses, jwt must be created/signed by partner login service, not created locally and should be encrypted
- (NSString *)createJWTTokenFromUsername:(NSString *)username password:(NSString *)password {
    NSDictionary <NSString *, NSString *> *header = @{@"alg": @"none", @"typ": @"JWT"};
    NSDictionary <NSString *, NSObject *> *payload = @{@"sub": username};
    NSData *headerJWTData = [NSJSONSerialization dataWithJSONObject:header options:NSJSONWritingPrettyPrinted error:nil];
    NSData *payloadJWTData = [NSJSONSerialization dataWithJSONObject:payload options:NSJSONWritingPrettyPrinted error:nil];
    NSString *headerJWTBase64 = [[headerJWTData base64EncodedStringWithOptions:0] stringByReplacingOccurrencesOfString:@"=" withString:@""];
    NSString *payloadJWTBase64 = [[payloadJWTData base64EncodedStringWithOptions:0] stringByReplacingOccurrencesOfString:@"=" withString:@""];
    
    return [NSString stringWithFormat:@"%@.%@", headerJWTBase64, payloadJWTBase64];
}

@end
import UIKit
import VouchrSDK

class VouchrSDKLoginManager: NSObject, VOAuthClient {
    var vouchrSDK:VOEngine
    var credential:Credential?
    var username:String?
    
    override init() {
        vouchrSDK = VOEngine.instance();
    }
    
    func login(viewController:UIViewController, completion:@escaping (VOUser) -> Void) {
            let username:String? = "someusername"
            let password:String? = "somepassword"
            self.loginToVouchrSDK(username: username, password: password, completion: completion)
    }
    
    func loginToVouchrSDK(username:String?, password:String?, completion:@escaping (VOUser) -> Void) {
        self.username = username;

        // Step 2
        let jwtToken = self.createJWTToken(username: username!, password: password!)
        // Step 3
        self.credential = VOCredential(dictionary: ["networkId": username!,
                                                      "network": "JWT_TEST",
                                                      "idToken": jwtToken]);
        
        // Step 4
        self.vouchrSDK.userManager.login(withCredentials: self.credential, authClient: self, onSuccess: {[unowned self] (user) -> Void in
                completion(user);
            }, onError: { [unowned self] (error) -> Void in
                // error handling here
        });
    }

    // Step 1
    func userForRegistration(with credential: VOCredential!, onSuccess: ((VOCredential?, VOSimpleUser?) -> Void)!, onError: ((Error?) -> Void)!) {
        onSuccess(credential, SimpleUser(firstName: "test", lastName: "user", email: self.username!, profileImageUrl: nil, birthday: nil));
    }
    
    // CRITICAL: for production uses, jwt must be created/signed by partner login service, not created locally and should be encrypted
    private func createJWTToken(username:String, password:String) -> String {
        let header:[String: String] = ["alg": "none", "typ": "JWT"]
        let payload:[String: String] = ["sub": username]
        
        let headerJWTData:Data = try! JSONSerialization.data(withJSONObject: header,options: JSONSerialization.WritingOptions.prettyPrinted)
        let payloadJWTData:Data = try! JSONSerialization.data(withJSONObject: payload, options: JSONSerialization.WritingOptions.prettyPrinted)
        let headerJWTBase64:String =  headerJWTData.base64EncodedString().replacingOccurrences(of: "=", with: "");
        let payloadJWTBase64:String = payloadJWTData.base64EncodedString().replacingOccurrences(of: "=", with: "");
        
        return String(format: "%@.%@", headerJWTBase64, payloadJWTBase64)
    }
}

Required Methods

The showLoginOnViewController:onCompletion method is called when a user needs to be logged in to proceed with the flow. Users can start with creation of a voucher without being logged in, but must be logged in to send it.

- (void)showLoginOnViewController:(UIViewController *)viewController onCompletion:(void(^)(NSError *error))completion;
func showLogin(on viewController: UIViewController!, onCompletion completion: ((Error?) -> Void)!)

Example Implementation

- (void)showLoginOnViewController:(UIViewController *)viewController onCompletion:(void(^)(NSError *error))completion {
    [manager loginFromViewController:viewController 
    	onSuccess:^{
    		if (completion) {
    			completion(nil);
    		}
    	} onError:^(NSError *error) {
    		if (completion) {
    			completion(error);
    		}
    	}];
}
func showLogin(on viewController: UIViewController!, onCompletion completion: ((Error?) -> Void)!) {
	self.facebookManager?.login(from:viewController, handler: {[weak self] (result: Any?, error: Error?) in
		if (completion != nil) {
			completion(error)
		}
	})
}