Embed UI in a WebView

The non-mobile Registration implementation normally uses popup windows to load social provider’s login screens. Popups do not work well on mobile devices. Instead, the Registration application is configured to redirect to the provider’s login screen, then on to the Registration UI server, and finally back to the original page.

How it Works

UIWebView-stringByEvaluatingJavaScriptFromString: Exchanges information between the iOS host app and the Janrain JavaScript, and UIWebViewDelegate-shouldStartLoadWithRequest:navigationType: Notifies the host app that the JavaScript has information to communicate to the host.

In this way, you can embed the Janrain Registration UI in any native mobile app, leveraging the flexibility of the UI to handle registration.

Prerequisites

Implementation

1. Starting the UI

Registration handles user registration and related flows. Typically each flow is embedded in one host webpage. To start the flow, include the standard block of JavaScript settings, and then run:

janrain.capture.ui.start();

Flows are configured separately for each instance of Registration, and can be customized. This example uses iPhone screen-sized optimized flows named webViewProfile and webViewSignIn. If you so choose, you can use the webViewDemo flow name with the markup in index-oneflow.html to have all screens on one page using one flow.

2. Settings

Use the following settings to make the UI use redirection:

Usage

Append the setting to janrain.settings to format the JavaScript call.

Example: janrain.settings.popup

Field Value Description
popup false The UI spawns new windows for identity provider sign-in by default. This flag forces the UI to operate in a single-window mode appropriate for operation inside a UIWebView.
capture.redirectFlow
true Required to configured the UI to operate in single-window mode.
tokenAction
‘url’ Configures Social Login to redirect after authentication.
type
’embed’ Configures Janrain UI to render embedded in the host page’s DOM, as opposed to rendering in a modal popup dialog.
redirectUri
location.href Configures Registration to redirect back to the host page after signing a user in.
capture.captureServer
domain url Configures the base URL of your Registration server instance. It will appear similar to 'https://yourappdomain.janraincapture.com';
tokenUrl url Unused in the redirect flow but must be set to an whitelisted domain for proper operation. Specifies the page to be redirected to after signing in. We suggest that you use the URL you set in the janrain.settings.capture.captureServer setting.

3. Interacting with Registration from the iOS Host App

The UIWebView message -(NSString *)stringByEvaluatingJavaScriptFromString:(NSString *) jsString serves as a bridge to inject and extract information from the UIWebView.

The UI can also emit information to the host app by initiating specially formed page loads, and responding to the UIWebViewDelegate-webView:shouldStartLoadWithRequest:navigationType: message.

For a discussion of this technique and links to open source implementations see this Stackoverflow question: http://stackoverflow.com/questions/9473582/ios-javascript-bridge

Also see the reference implementation’s JavaScript iOS bridge in janrain-bridge.js file located in the CaptureStandardRegistrationFlow Xcode example project.

4. Setting the Access Token

After the UI starts, you can call:

janrain.capture.ui.createCaptureSession("accessToken");

5. Getting the Access Token

To retrieve the Registration access token (which you can use with the API directly,) register an event handler to the onCaptureLoginSuccess event and pass the token with the iOS JS bridge technique:

janrain.events.onCaptureLoginSuccess.addHandler(function (result) {
    if (result.accessToken && !result.oneTime) {
        document.location.href = "janrain:accessToken=" + result.accessToken;
    }
});

… and monitor request URLs in UIWebView-webView:shouldStartLoadWithRequest:navigationType:

if ([request.URL.scheme isEqualToString:@"janrain"])
{
    NSString *token = [[request.URL.absoluteString componentsSeparatedByString:@"="] objectAtIndex:1];
    [self sendOptionalDelegateMessage:@selector(signInDidSucceedWithAccessToken:) withArgument:token];
}

6. Handling JavaScript Events in the Host App

janrain-bridge.js in the reference implementation bridges all Janrain JavaScript events to the iOS host app. Add event handlers to the reference implementations jsEventHandlers object:

/**
 * NSString -> NSArray map with (void)^(NSDictionary *eventArgs) blocks/handlers
 * It is okay to add handlers to this structure from outside of this class.
 */
@property(nonatomic, strong) id jsEventHandlers;

For example, the reference implementation adds a handler to onCaptureLoginSuccess:

[self.jsEventHandlers setObject:[NSMutableArray array]forKey:@"onCaptureLoginSuccess"];
[[self.jsEventHandlers objectForKey:@"onCaptureLoginSuccess"] addObject:[^(id eventArgs){
    NSDictionary *result = [eventArgs objectAtIndex:0];
    [self sendOptionalDelegateMessage:@selector(signInDidSucceedWithAccessToken:) withArgument:result];
} copy]];

An Example

The Xcode project, CaptureStandardRegistrationFlow, is a working example of running the Registration user registration solution in a UIWebView. It loads static pages hosted in the gh-pages branch of this Github repository. Each page embeds the UI and invokes a specific flow when loaded.

Example HTML Files