بنقرة واحدة
oidc-hosted-page-ios
Implement "Sign in with SSO" in native iOS/Swift applications using SSOJet OIDC with AppAuth.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Implement "Sign in with SSO" in native iOS/Swift applications using SSOJet OIDC with AppAuth.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Implement Machine-to-Machine (M2M) authentication using SSOJet OAuth2 Client Credentials flow for backend services and daemons.
Implement "Sign in with SSO" in native Android/Kotlin applications using SSOJet OIDC with AppAuth.
Implement "Sign in with SSO" in Angular SPA applications using SSOJet OIDC with PKCE.
Implement "Sign in with SSO" in ASP.NET Core applications using SSOJet OIDC middleware.
Implement "Sign in with SSO" in Go applications using SSOJet OIDC Authorization Code flow.
Implement "Sign in with SSO" in Java Spring Boot applications using SSOJet OIDC with Spring Security.
| name | oidc-hosted-page-ios |
| description | Implement "Sign in with SSO" in native iOS/Swift applications using SSOJet OIDC with AppAuth. |
This expert AI assistant guide walks you through integrating "Sign in with SSO" functionality into an existing iOS application using SSOJet as an OIDC identity provider via AppAuth for iOS.
openid/AppAuth-iOS.com.example.myapp://auth/callback).Note: For native/mobile apps, use Authorization Code with PKCE (no Client Secret on the device).
Add AppAuth via Swift Package Manager:
https://github.com/openid/AppAuth-iOS.git.Or via CocoaPods:
# Podfile
pod 'AppAuth'
pod install
Add a custom URL scheme in your Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.example.myapp</string>
</array>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
</dict>
</array>
Create an auth configuration helper (e.g., AuthConfig.swift):
// AuthConfig.swift
import Foundation
struct AuthConfig {
static let issuerURL = URL(string: "https://auth.ssojet.com")!
static let clientID = "your_client_id"
static let redirectURI = URL(string: "com.example.myapp://auth/callback")!
static let scopes = ["openid", "profile", "email"]
}
Create a centralised auth manager (e.g., AuthManager.swift):
// AuthManager.swift
import UIKit
import AppAuth
class AuthManager: NSObject {
static let shared = AuthManager()
var currentAuthorizationFlow: OIDExternalUserAgentSession?
var authState: OIDAuthState?
func login(from viewController: UIViewController, loginHint: String?, completion: @escaping (Result<OIDAuthState, Error>) -> Void) {
// Discover OIDC configuration
OIDAuthorizationService.discoverConfiguration(forIssuer: AuthConfig.issuerURL) { config, error in
guard let config = config else {
completion(.failure(error ?? NSError(domain: "OIDC", code: -1, userInfo: [NSLocalizedDescriptionKey: "Discovery failed"])))
return
}
// Build authorization request
var additionalParams: [String: String] = [:]
if let hint = loginHint, !hint.isEmpty {
additionalParams["login_hint"] = hint
}
let request = OIDAuthorizationRequest(
configuration: config,
clientId: AuthConfig.clientID,
scopes: AuthConfig.scopes,
redirectURL: AuthConfig.redirectURI,
responseType: OIDResponseTypeCode,
additionalParameters: additionalParams
)
// Launch auth flow
self.currentAuthorizationFlow = OIDAuthState.authState(
byPresenting: request,
presenting: viewController
) { authState, error in
if let authState = authState {
self.authState = authState
print("Authenticated! Access Token: \(authState.lastTokenResponse?.accessToken ?? "nil")")
completion(.success(authState))
} else {
print("OIDC Error: \(error?.localizedDescription ?? "Unknown error")")
completion(.failure(error ?? NSError(domain: "OIDC", code: -1)))
}
}
}
}
func logout() {
authState = nil
}
}
// AppDelegate.swift (or SceneDelegate.swift)
import AppAuth
// In AppDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if let flow = AuthManager.shared.currentAuthorizationFlow,
flow.resumeExternalUserAgentFlow(with: url) {
AuthManager.shared.currentAuthorizationFlow = nil
return true
}
return false
}
// If using SceneDelegate:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
if let flow = AuthManager.shared.currentAuthorizationFlow,
flow.resumeExternalUserAgentFlow(with: url) {
AuthManager.shared.currentAuthorizationFlow = nil
}
}
// LoginViewController.swift
import UIKit
class LoginViewController: UIViewController {
private let emailTextField = UITextField()
private let passwordTextField = UITextField()
private let signInButton = UIButton(type: .system)
private let ssoToggleButton = UIButton(type: .system)
private var isSSO = false
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
private func setupUI() {
view.backgroundColor = .systemBackground
title = "Sign In"
emailTextField.placeholder = "Email"
emailTextField.keyboardType = .emailAddress
emailTextField.borderStyle = .roundedRect
passwordTextField.placeholder = "Password"
passwordTextField.isSecureTextEntry = true
passwordTextField.borderStyle = .roundedRect
signInButton.setTitle("Sign In", for: .normal)
signInButton.addTarget(self, action: #selector(handleSignIn), for: .touchUpInside)
ssoToggleButton.setTitle("Sign in with SSO", for: .normal)
ssoToggleButton.addTarget(self, action: #selector(toggleSSO), for: .touchUpInside)
let stack = UIStackView(arrangedSubviews: [emailTextField, passwordTextField, signInButton, ssoToggleButton])
stack.axis = .vertical
stack.spacing = 16
stack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24),
stack.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24),
])
}
@objc private func toggleSSO() {
isSSO.toggle()
passwordTextField.isHidden = isSSO
signInButton.setTitle(isSSO ? "Continue with SSO" : "Sign In", for: .normal)
ssoToggleButton.setTitle(isSSO ? "Back to Password Login" : "Sign in with SSO", for: .normal)
}
@objc private func handleSignIn() {
let email = emailTextField.text ?? ""
if isSSO {
AuthManager.shared.login(from: self, loginHint: email) { result in
DispatchQueue.main.async {
switch result {
case .success:
let dashboard = DashboardViewController()
self.navigationController?.pushViewController(dashboard, animated: true)
case .failure(let error):
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}
}
} else {
print("Processing traditional login...")
}
}
}
OIDAuthState.authState(byPresenting:) call in a coordinator or use ASWebAuthenticationSession directly.