{"_id":"5ab565f212d24900747242ac","category":{"_id":"5ab565f112d249007472429b","version":"5ab565f112d2490074724298","project":"57c88b374434350e00509d7f","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-11-05T21:53:37.386Z","from_sync":false,"order":2,"slug":"reference","title":"Reference"},"project":"57c88b374434350e00509d7f","parentDoc":null,"user":"55e5ba046015ce1900eadb8e","version":{"_id":"5ab565f112d2490074724298","project":"57c88b374434350e00509d7f","__v":1,"createdAt":"2018-03-23T20:39:13.299Z","releaseDate":"2018-03-23T20:39:13.299Z","categories":["5ab565f112d2490074724299","5ab565f112d249007472429a","5ab565f112d249007472429b","5ab565f112d249007472429c"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"3.6.0","version":"3.6.0"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-03-23T15:29:38.991Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":10,"body":"Validating your users' input is a core part of the onboarding process. The Primer iOS SDK can notify you about the most important events, be it signup, login, password recovery, or anything else, and let you handle them.\n\n####Delegate Protocol\n\nIf you'd like to be notified about the progress of your users, and receive the information they provide as an input, you should conform to the `PMRExperienceDelegate` protocol. Usually the best place to do so is a class that manages your user system. Once you have an instance of a conforming class you can set it as the experience delegate. Note that the SDK only holds a weak reference to this object (as is the norm with the delegation pattern), so your app should manage it.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"id <PMRExperienceDelegate> userManager = ...\\n[Primer setExperienceDelegate:userManager];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let userManager: PMRExperienceDelegate = ...\\nPrimer.setExperienceDelegate(userManager)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n####Authentication Methods\n\nAll methods of the protocol are optional. They provide you a dictionary of the relevant input fields that consist of the string key and the attached value. Most methods also have a completion block that you always have to call, even if in an asynchronous manner. Until you do so, the SDK displays a loading overlay to the user.\n\nTo validate any input fields on a screen implement the `-validateFields:completion:` method. It gets called after a screen is submitted with any inputs on it. The dictionary contains all fields of the screen.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)validateFields:(NSDictionary<NSString *, id> *)fields completion:(PMRValidationBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func validateFields(_ fields: [String : Any], completion: :::at:::escaping PMRValidationBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nWhen a login flow is submitted, the `-logInWithFields:completion:` method gets called by the delegate. The dictionary contains all fields of the flow. Note that the non-sensitive fields get added as user properties after a successful validation.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)logInWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRUserValidationBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func logIn(withFields fields: [String : Any], completion: @escaping PMRUserValidationBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nWhen a signup flow is submitted, the delegate calls the `-signUpWithFields:completion:` method. The dictionary contains all fields of the flow. Note that the non-sensitive fields get added as user properties after a successful validation.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)signUpWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRUserValidationBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func signUp(withFields fields: [String : Any], completion: @escaping PMRUserValidationBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nWhen a recover password flow is submitted, the delegate calls the `-recoverPasswordWithFields:completion:` method. The dictionary contains all fields of the flow.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)recoverPasswordWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRValidationBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func recoverPassword(withFields fields: [String : Any], completion: @escaping PMRValidationBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nTo get notified when an experience closes, implement the `-willCloseWithFields:` method. It gets called when an experience is about to get dismissed (except for successful logins and signups). The dictionary contains all fields entered up until this point.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)willCloseWithFields:(NSDictionary<NSString *, id> *)fields;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func willClose(withFields fields: [String : Any])\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nWhen a `Submit Fields` action is executed you have the opportunity to handle the given fields. Once done, let the SDK know with the completion block's parameter whether the success action should be executed (if any).\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)handleFields:(NSDictionary<NSString *, id> *)fields completion:(PMRSuccessBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func handleFields(_ fields: [String : Any], completion: @escaping PMRSuccessBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n####Validation Result\n\nWhen implementing a delegate method that has a completion block parameter (either a `PMRValidationBlock` or a `PMRUserValidationBlock`) the SDK expects you to validate the fields and call the completion block. Both have an optional `PMRValidationResult` parameter, and the user validation block has an additional string parameter for the user's identifier in cases when a user will be logged in after a successful validation.\n\nIf the validation succeeds (i.e. there are no invalid fields or errors), call the completion block with either a new validation result instance or `nil` as the first parameter. Also, when the block is a `PMRUserValidationBlock`, pass in the unique user identifier as the second parameter.\n\nIf the validation fails (because there's at least one invalid field or an error occurred), call the completion block with a validation result that you invalidated. There are multiple ways to do that:\n* invalidate the result with an error message (useful when an error occurs but there's no invalid field)\n* invalidate a field (its default error message will be displayed)\n* invalidate a field with a custom error message\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"PMRValidationResult *result = [[PMRValidationResult alloc] init];\\n\\n[result invalidateWithErrorMessage:@\\\"Error message.\\\"];\\n\\n// or\\n\\n[result invalidateField:@\\\"key\\\"];\\n\\n// or\\n\\n[result invalidateField:@\\\"key\\\" withErrorMessage:@\\\"Error message.\\\"];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let result = PMRValidationResult()\\n\\nresult.invalidateWithErrorMessage(\\\"Error message.\\\")\\n\\n// or\\n\\nresult.invalidateField(\\\"key\\\")\\n\\n// or\\n\\nresult.invalidateField(\\\"key\\\", withErrorMessage: \\\"Error message.\\\")\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n####Facebook Login\n\nIf you'd like to set Facebook Login up as part of the Primer onboarding experience, it's easy to do so. Just integrate the v4+ version of the Facebook iOS SDK by following their <a href=\"https://developers.facebook.com/docs/ios/getting-started\" target=\"_blank\">Getting Started</a> guide. To properly load all necessary classes, go to the `Build Settings` tab of your app target's settings in Xcode, and search for `Other Linker Flags`. Then add `-ObjC` to the list of flags. That's all you need to set Facebook authentication up.\n\nWhen a Facebook authentication finishes the `-validateFacebookUserWithFields:completion:` method gets called by the delegate. The dictionary contains all requested Graph API fields that Facebook returned to the SDK. Note that these fields get added as user properties after a successful validation. In the completion block of this method you have a third parameter, that lets you signal to the SDK whether the user is a new signup.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (void)validateFacebookUserWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRFacebookUserValidationBlock)completion;\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func validateFacebookUser(withFields fields: [String : Any], completion: @escaping PMRFacebookUserValidationBlock)\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"In addition to the Graph API fields the SDK also adds `profile_pic` to the dictionary, setting it to the 800px x 800px user avatar URL gathered from Facebook. If you wish, you can overwrite this at any time by [appending a user property](doc:user-management#section-user-properties) with the same key.\"\n}\n[/block]","excerpt":"","slug":"authentication","type":"basic","title":"Authentication"}
Validating your users' input is a core part of the onboarding process. The Primer iOS SDK can notify you about the most important events, be it signup, login, password recovery, or anything else, and let you handle them. ####Delegate Protocol If you'd like to be notified about the progress of your users, and receive the information they provide as an input, you should conform to the `PMRExperienceDelegate` protocol. Usually the best place to do so is a class that manages your user system. Once you have an instance of a conforming class you can set it as the experience delegate. Note that the SDK only holds a weak reference to this object (as is the norm with the delegation pattern), so your app should manage it. [block:code] { "codes": [ { "code": "id <PMRExperienceDelegate> userManager = ...\n[Primer setExperienceDelegate:userManager];", "language": "objectivec" }, { "code": "let userManager: PMRExperienceDelegate = ...\nPrimer.setExperienceDelegate(userManager)", "language": "swift" } ] } [/block] ####Authentication Methods All methods of the protocol are optional. They provide you a dictionary of the relevant input fields that consist of the string key and the attached value. Most methods also have a completion block that you always have to call, even if in an asynchronous manner. Until you do so, the SDK displays a loading overlay to the user. To validate any input fields on a screen implement the `-validateFields:completion:` method. It gets called after a screen is submitted with any inputs on it. The dictionary contains all fields of the screen. [block:code] { "codes": [ { "code": "- (void)validateFields:(NSDictionary<NSString *, id> *)fields completion:(PMRValidationBlock)completion;", "language": "objectivec" }, { "code": "func validateFields(_ fields: [String : Any], completion: @escaping PMRValidationBlock)", "language": "swift" } ] } [/block] When a login flow is submitted, the `-logInWithFields:completion:` method gets called by the delegate. The dictionary contains all fields of the flow. Note that the non-sensitive fields get added as user properties after a successful validation. [block:code] { "codes": [ { "code": "- (void)logInWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRUserValidationBlock)completion;", "language": "objectivec" }, { "code": "func logIn(withFields fields: [String : Any], completion: @escaping PMRUserValidationBlock)", "language": "swift" } ] } [/block] When a signup flow is submitted, the delegate calls the `-signUpWithFields:completion:` method. The dictionary contains all fields of the flow. Note that the non-sensitive fields get added as user properties after a successful validation. [block:code] { "codes": [ { "code": "- (void)signUpWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRUserValidationBlock)completion;", "language": "objectivec" }, { "code": "func signUp(withFields fields: [String : Any], completion: @escaping PMRUserValidationBlock)", "language": "swift" } ] } [/block] When a recover password flow is submitted, the delegate calls the `-recoverPasswordWithFields:completion:` method. The dictionary contains all fields of the flow. [block:code] { "codes": [ { "code": "- (void)recoverPasswordWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRValidationBlock)completion;", "language": "objectivec" }, { "code": "func recoverPassword(withFields fields: [String : Any], completion: @escaping PMRValidationBlock)", "language": "swift" } ] } [/block] To get notified when an experience closes, implement the `-willCloseWithFields:` method. It gets called when an experience is about to get dismissed (except for successful logins and signups). The dictionary contains all fields entered up until this point. [block:code] { "codes": [ { "code": "- (void)willCloseWithFields:(NSDictionary<NSString *, id> *)fields;", "language": "objectivec" }, { "code": "func willClose(withFields fields: [String : Any])", "language": "swift" } ] } [/block] When a `Submit Fields` action is executed you have the opportunity to handle the given fields. Once done, let the SDK know with the completion block's parameter whether the success action should be executed (if any). [block:code] { "codes": [ { "code": "- (void)handleFields:(NSDictionary<NSString *, id> *)fields completion:(PMRSuccessBlock)completion;", "language": "objectivec" }, { "code": "func handleFields(_ fields: [String : Any], completion: @escaping PMRSuccessBlock)", "language": "swift" } ] } [/block] ####Validation Result When implementing a delegate method that has a completion block parameter (either a `PMRValidationBlock` or a `PMRUserValidationBlock`) the SDK expects you to validate the fields and call the completion block. Both have an optional `PMRValidationResult` parameter, and the user validation block has an additional string parameter for the user's identifier in cases when a user will be logged in after a successful validation. If the validation succeeds (i.e. there are no invalid fields or errors), call the completion block with either a new validation result instance or `nil` as the first parameter. Also, when the block is a `PMRUserValidationBlock`, pass in the unique user identifier as the second parameter. If the validation fails (because there's at least one invalid field or an error occurred), call the completion block with a validation result that you invalidated. There are multiple ways to do that: * invalidate the result with an error message (useful when an error occurs but there's no invalid field) * invalidate a field (its default error message will be displayed) * invalidate a field with a custom error message [block:code] { "codes": [ { "code": "PMRValidationResult *result = [[PMRValidationResult alloc] init];\n\n[result invalidateWithErrorMessage:@\"Error message.\"];\n\n// or\n\n[result invalidateField:@\"key\"];\n\n// or\n\n[result invalidateField:@\"key\" withErrorMessage:@\"Error message.\"];", "language": "objectivec" }, { "code": "let result = PMRValidationResult()\n\nresult.invalidateWithErrorMessage(\"Error message.\")\n\n// or\n\nresult.invalidateField(\"key\")\n\n// or\n\nresult.invalidateField(\"key\", withErrorMessage: \"Error message.\")", "language": "swift" } ] } [/block] ####Facebook Login If you'd like to set Facebook Login up as part of the Primer onboarding experience, it's easy to do so. Just integrate the v4+ version of the Facebook iOS SDK by following their <a href="https://developers.facebook.com/docs/ios/getting-started" target="_blank">Getting Started</a> guide. To properly load all necessary classes, go to the `Build Settings` tab of your app target's settings in Xcode, and search for `Other Linker Flags`. Then add `-ObjC` to the list of flags. That's all you need to set Facebook authentication up. When a Facebook authentication finishes the `-validateFacebookUserWithFields:completion:` method gets called by the delegate. The dictionary contains all requested Graph API fields that Facebook returned to the SDK. Note that these fields get added as user properties after a successful validation. In the completion block of this method you have a third parameter, that lets you signal to the SDK whether the user is a new signup. [block:code] { "codes": [ { "code": "- (void)validateFacebookUserWithFields:(NSDictionary<NSString *, id> *)fields completion:(PMRFacebookUserValidationBlock)completion;", "language": "objectivec" }, { "code": "func validateFacebookUser(withFields fields: [String : Any], completion: @escaping PMRFacebookUserValidationBlock)", "language": "swift" } ] } [/block] [block:callout] { "type": "info", "body": "In addition to the Graph API fields the SDK also adds `profile_pic` to the dictionary, setting it to the 800px x 800px user avatar URL gathered from Facebook. If you wish, you can overwrite this at any time by [appending a user property](doc:user-management#section-user-properties) with the same key." } [/block]