We all know that Apple introduce Extensible Enterprise Single Sign-on Extension on iOS 13. Here
is the demo video presented by Apple.
There are two types of Extension,
Redirect and
Credential
I want to work with Redirect Extension.
The below code shown in demo video.
class ViewController: UIViewController {
var authController : ASAuthorizationController?
let authProvider = ASAuthorizationSingleSignOnProvider(identityProvider: URL(string: "https://example.com")!)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func login(_ sender: Any) {
if self.authProvider.canPerformAuthorization {
let request = self.authProvider.createRequest()
request.requestedOperation = ASAuthorization.OpenIDOperation.operationLogin
self.authController = ASAuthorizationController(authorizationRequests: [request])
self.authController?.delegate = self
self.authController?.presentationContextProvider = self
self.authController?.performRequests()
} else {
print("failed to perform authorization")
}
}
}
How can I get the identity provider URL.
So my question is that how to implement Redirect Extension in my app and how to add identity provider url.
Thanks in Advance.
Related
I want to implement Single Sign On Extension for an iOS 13 app. I've already gone through various blogs, but there seems to be no standard solution available for implementing single sign-on extensions.
I'm trying to build up my own SSO solution, but I've not yet been able to implement it successfully. Here is the code that I have written so far:
import UIKit
import AuthenticationServices
class ViewController: UIViewController {
#IBOutlet weak var loginButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func loginButtonPushed(_ sender: Any) {
let issuer = URL(fileURLWithPath: "https://url_here")
let ssoProvider = ASAuthorizationSingleSignOnProvider(identityProvider: issuer)
let request = ssoProvider.createRequest()
request.requestedScopes = [.fullName, .email]
request.authorizationOptions = [
URLQueryItem(name: "client_id", value: "client_id"),
URLQueryItem(name: "response_type", value: "code")
]
let authzController = ASAuthorizationController(authorizationRequests: [request])
authzController.delegate = self
authzController.presentationContextProvider = self
authzController.performRequests()
}
}
extension ViewController: ASAuthorizationControllerDelegate {
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error.
}
}
extension ViewController: ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
}
More generally, I'd like to ask:
What are the prerequisites to an SSO solution that we need to consider before implementation.
Questions Like:
What type of server required,
Which auth services need to implement and why,
Do we need to consider Apple configurator2 for implementing this?
Is there anything that need to be done at server-side? If yes, please explain it. I need to understand both the back-end and development perspectives.
There are two different types of extensions provided by iOS 13 for SSO implementations: redirect and credential.
So, how should we decide which extension to implement and why? What circumstances do we need to consider in making the decision?
The sample app here https://getstream.io/ios-activity-feed/tutorial/ is working good using the sample Client api key, app id, and token. Really uploads and downloads Posts that are viewable in the dashboard. However, when I change the api key, app id, and token to mine (I submitted the email to an online Nodejs get stream backend to produce the token), though I am able to push a Post and view in the dashboard, the download fails with this error message:
JSON decoding error: The data couldn’t be read because it isn’t in the correct format..
I compare the data in the two dashboards online and noted that Post in both are of the same types.
At first, I really thought that the FlatFeedViewController in the sample app was a fast and clean solution.
I used 100% code from this link.
In AppDelegate:
apiKey: "xxxxxxxx",
appId: "xxxx",
token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
Client.shared.getCurrentUser(typeOf: GetStreamActivityFeed.User.self) { result in
if result.error == nil, let viewController = self.window?.rootViewController as? ViewController {
viewController.reloadData()
}
}
In the viewcontroller:
class ViewController: FlatFeedViewController<GetStreamActivityFeed.Activity> {
let textToolBar = TextToolBar.make()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
appDelegate.getStream()
if let feedId = FeedId(feedSlug: "timeline") {
let timelineFlatFeed = Client.shared.flatFeed(feedId)
presenter = FlatFeedPresenter<GetStreamActivityFeed.Activity>(flatFeed: timelineFlatFeed, reactionTypes: [.likes, .comments])
}
super.viewDidLoad()
setupTextToolBar()
subscribeForUpdates()
}
func setupTextToolBar() {
textToolBar.addToSuperview(view, placeholderText: "Share something...")
// Enable URL unfurling.
textToolBar.linksDetectorEnabled = true
// Enable image picker.
textToolBar.enableImagePicking(with: self)
textToolBar.sendButton.addTarget(self, action: #selector(save(_:)), for: .touchUpInside)
}
#objc func save(_ sender: UIButton) {
// Hide the keyboard.
view.endEditing(true)
if textToolBar.isValidContent, let presenter = presenter {
textToolBar.addActivity(to: presenter.flatFeed) { result in
print(result) // It will print the added activity or error.
}
}
}
I expected the uploaded Posts to be downloaded in the app. But the decoding error results. The error is thrown in the public final class Activity, specifically in the function: public required init(from decoder: Decoder) throws {
Please help.
I have done live streaming for a single platform like facebook using LFLivekit. When I am trying for two platforms it's not happening.
Code:
import UIKit
import LFLiveKit
class VideoViewController: UIViewController {
var sessionO: LFLiveSession =
{
let audioConfiguration = LFLiveAudioConfiguration.defaultConfiguration(for: LFLiveAudioQuality.high)
let videoConfiguration = LFLiveVideoConfiguration.defaultConfiguration(for: LFLiveVideoQuality.low3)
let session = LFLiveSession(audioConfiguration: audioConfiguration, videoConfiguration: videoConfiguration)
return session!
}()
override func viewDidLoad() {
super.viewDidLoad()
self.streamUrl = "live-api-s.facebook.com:80/rtmp/"
self.streamName = "17XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
self.sessionO.delegate = self
self.sessionO.preView = self.view
self.sessionO.running = true
}
override func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear(animated)
let stream = LFLiveStreamInfo()
stream.url = "rtmp://\(self.streamUrl!)/LiveApp/\(self.streamName!)"
self.sessionO.startLive(stream)
}
}
Note: If I create one more session and stream also for youtube it is not working.
We need to create separate RTMP connection and create the listener.
fbRtmpStream = RTMPStream(connection: fbRtmpConnection)
ytRtmpStream = RTMPStream(connection: ytRtmpConnection)
self.fbRtmpConnection1.addEventListener(Event.RTMP_STATUS, selector:#selector(self.fbRtmpStatusHandler1(_:)), observer: self)
self.fbRtmpConnection1.connect("rtmp://live-api-s.facebook.com:80/rtmp/")
self.fbStreamName1 = "xxxxxx"
self.ytRtmpConnection.addEventListener(Event.RTMP_STATUS, selector:#selector(self.ytRtmpStatusHandler(_:)), observer: self)
self.ytRtmpConnection.connect("rtmp://a.rtmp.youtube.com/live2/LiveApp/")
self.ytStreamName = "xxxxxxxxx"
This might not be the solution you're looking for source
Multiple server upload main problem is the error handling more complex, for example, the way out of the problem,this has not yet been good how to deal with. source
So! LFLiveKit does not support multiple server
I am trying to get the authentication token to be able to grab a user's info. I registered my app in the instagram api page and everything seems to work except that I am not able to retrieve an authentication token or anything information. (I think it might be because of the redirect url i just made a dummy url) I can login to my instagram account and authorize my app to retrieve information but I dont get anything printed on my console so Im assuming im not being able to retrieve anything.
the code:
import UIKit
import WebKit
class ViewController3: UIViewController, UIWebViewDelegate {
#IBOutlet weak var WebView1: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let authURL = String(format: "%#?client_id=%#&redirect_uri=%#&response_type=token&scope=%#&DEBUG=True", arguments: [API.INSTAGRAM_AUTHURL,API.INSTAGRAM_CLIENT_ID,API.INSTAGRAM_REDIRECT_URI, API.INSTAGRAM_SCOPE])
let urlRequest = URLRequest.init(url: URL.init(string: authURL)!)
WebView1.load(urlRequest)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var tts = segue.destination as! Manage_Ad_VC
tts.S_Media_R = "Instagram"
}
func WebView1(_ WebView1: UIWebView, shouldStartLoadWith request:URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
return checkRequestForCallbackURL(request: request)
}
func checkRequestForCallbackURL(request: URLRequest) -> Bool {
print("Instagram authentication token ==")
let requestURLString = (request.url?.absoluteString)! as String
if requestURLString.hasPrefix(API.INSTAGRAM_REDIRECT_URI) {
let range: Range<String.Index> = requestURLString.range(of: "#access_token=")!
handleAuth(authToken: requestURLString.substring(from: range.upperBound))
return false;
}
return true
}
func handleAuth(authToken: String) {
print("Instagram authentication token ==", authToken)
}
}
struct API {
static let INSTAGRAM_AUTHURL = "https://api.instagram.com/oauth/authorize/"
static let INSTAGRAM_CLIENT_ID = "myclientidgoeshere"
static let INSTAGRAM_CLIENTSERCRET = " myclientsercretgoeshere "
static let INSTAGRAM_REDIRECT_URI = "http://www.dummyurl.com/just_a_made_up_dummy_url"
static let INSTAGRAM_ACCESS_TOKEN = ""
static let INSTAGRAM_SCOPE = "follower_list+public_content" /* add whatever scope you need https://www.instagram.com/developer/authorization/ */
}
enter image description here
U have used WKWebView and UIWebViewDelegate. It is not WKWebView delegate. This view has been inherited from UIView - not from uiwebview - that's why delegates methods does not work. Try to use WKNavigationDelegate with its methods.
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let url = request.url, url.host == "URL FOR OAUTH GOES HERE" {
if url.absoluteString.range(of: "access_token") != nil {
let urlParts = url.absoluteString.components(separatedBy: "=")
let code = urlParts[1]
let userInfoURL = "https://api.instagram.com/v1/users/self/?access_token=" + code
//Make request with the userInfoURL to retrieve the user Info.
}
}
return true
}
We need "Access token" to go further.But it seems empty in your case.Try to run local server either through node/jupiter/MAMP or anything and check your localhost page is popping up.
Once your localhost is up and running.Please paste the below link in the browser by replacing the client_id to yours.
https://www.instagram.com/oauth/authorize/?client_id=Your_Client_Id&redirect_uri=http://localhost:8000&response_type=token&scope=public_content
Make sure you are giving the same redirect uri while you registered.
Please follow this link for further clarification
Click on Authorize in the page to be displayed in the browser.And check the URL in the browser, your access token would be passed for the next page.Copy this token and use it in the code
Between the pod spec and what is currently on S.O. I had a tough time figuring out how to get speech-to-text working using SpeechKit + CocoaPod + Swift. Finally got it working so figured I'd help the next poor soul that comes looking for help! :)
First install the CocoaPod: https://cocoapods.org/pods/SpeechKit
Add #import <SpeechKit/SpeechKit.h> to your bridging header
Login to Nuance's dev portal and create an app: https://developer.nuance.com/
Clean up the demo code so that is is more organized. I just wanted as much of the code to be in one place as possible so you can see a fully working implementation.
Then create a UIViewController and add the following code with the correct credentials:
import UIKit
import SpeechKit
class SpeechKitDemo: UIViewController, SKTransactionDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//!!link this to a corresponding button on the UIViewController in I.B.
#IBAction func tappedButton(sender: AnyObject) {
// All fields are required.
// Your credentials can be found in your Nuance Developers portal, under "Manage My Apps".
let SKSAppKey = "[Get this from the nuance app info page]";
let SKSAppId = "[Get this from the nuance app info page]";
let SKSServerHost = "[Get this from the nuance app info page]";
let SKSServerPort = "[Get this from the nuance app info page]";
let SKSLanguage = "eng-USA";
let SKSServerUrl = "nmsps://\(SKSAppId)#\(SKSServerHost):\(SKSServerPort)"
let session = SKSession(URL: NSURL(string: SKSServerUrl), appToken: SKSAppKey)
//this starts a transaction that listens for voice input
let transaction = session.recognizeWithType(SKTransactionSpeechTypeDictation,
detection: .Short,
language: SKSLanguage,
delegate: self)
print(transaction)
}
//required delegate methods
func transactionDidBeginRecording(transaction: SKTransaction!) { }
func transactionDidFinishRecording(transaction: SKTransaction!) { }
func transaction(transaction: SKTransaction!, didReceiveRecognition recognition: SKRecognition!) {
//Take the best result
let topRecognitionText = recognition.text;
print("Best rec test: \(topRecognitionText)")
//Or iterate through the NBest list
let nBest = recognition.details;
for phrase in (nBest as! [SKRecognizedPhrase]!) {
let text = phrase.text;
let confidence = phrase.confidence;
print("\(confidence): \(text)")
}
}
func transaction(transaction: SKTransaction!, didReceiveServiceResponse response: [NSObject : AnyObject]!) { }
func transaction(transaction: SKTransaction!, didFinishWithSuggestion suggestion: String!) { }
func transaction(transaction: SKTransaction!, didFailWithError error: NSError!, suggestion: String!) { }
}