webviewsingle-sign-onaerogear

AeroGear SSO Login using Keycloak backend Embedded Safari Browser Instead of External Safari Browser


I am working on a project which needs SSO Login Feature, I have Implemented AeroGear SSO Login but the issue is that it opens the authentication website in Safari browser (Exits the main app and then open the browser) But I want not to leave the App to authentication, Is there any way? I can use an embedded web view within the App, which will be helpful to authenticate the user within the app.

Here is the demo code I am Using. (Here is Source of Example Code)

import UIKit

import AeroGearHttp
import AeroGearOAuth2

let HOST = "http://localhost:8080"

extension String {
/// Encode a String to Base64
func toBase64() -> String {
    return Data(self.utf8).base64EncodedString()
}

/// Decode a String from Base64. Returns nil if unsuccessful.
func fromBase64() -> String? {
    guard let data = Data(base64Encoded: self) else { return nil }
    return String(data: data, encoding: .utf8)
}
}

class ViewController: UIViewController {
var userInfo: OpenIdClaim?
var keycloakHttp = Http()
var images: [UIImage] = []
var currentIndex = 0
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from 
 a nib.
 }

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func goPreviousImage(_ sender: UIButton) {
    if  self.currentIndex > 0 {
        self.currentIndex -= 1
    }
    self.imageView.image = self.images[self.currentIndex]
}

@IBAction func goNextImage(_ sender: UIButton) {
    if  self.currentIndex < self.images.count - 1{
        self.currentIndex += 1
    }
    self.imageView.image = self.images[self.currentIndex]
}



@IBAction func loginAsKeycloak(_ sender: AnyObject) {
    let keycloakConfig = KeycloakConfig(
        clientId: "sharedshoot-third-party",
        host: HOST,
        realm: "shoot-realm",
        isOpenIDConnect: true)
    let oauth2Module = AccountManager.addKeycloakAccount(config: 
     keycloakConfig)
    self.keycloakHttp.authzModule = oauth2Module
    oauth2Module.login {(accessToken: AnyObject?, claims: 
     OpenIdClaim?, error: NSError?) in
        self.userInfo = claims
        if let userInfo = claims {
            if let name = userInfo.name {
                self.nameLabel.text = "Hello \(name)"
            }
        }

Solution

  • I got the solution by just adding one line

    keycloakConfig.webView = .embeddedWebView // Open webview within the app
    

    Add this line after setting the KeyCloak Config. Here is how to do it

       let keycloakConfig = KeycloakConfig(
        clientId: "sharedshoot-third-party",
        host: HOST,
        realm: "shoot-realm",
        isOpenIDConnect: true)
    
    keycloakConfig.webView = .embeddedWebView // Open webView within the app
    
    let oauth2Module = AccountManager.addKeycloakAccount(config: 
     keycloakConfig)
    self.keycloakHttp.authzModule = oauth2Module
    oauth2Module.login {(accessToken: AnyObject?, claims: 
     OpenIdClaim?, error: NSError?) in
        self.userInfo = claims
        if let userInfo = claims {
            if let name = userInfo.name {
                self.nameLabel.text = "Hello \(name)"
            }
        }