I'm currently trying to complete the OAuth dance with the Deezer API.
I have created a Deezer app on their site and full fill required fields.
I'm not using the Deezer SDK as it's deprecated since a long time ago.
I'm loading the request with a WKWebView and the request looks like :
https://connect.deezer.com/oauth/auth.php?app_id=MY_APP_ID&redirect_uri=MY_REDIRECT_URL&response_type=token&perms=basic_access
This open a webview displaying an auth form.
After i login with my deezer account credentials, i'm supposed to be redirected to the previous specified url MY_REDIRECT_URL.
But i intercept the redirection like this :
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Swift.Void) {
if !isLoading {
isLoading = true
}
if let redirectedUrl = navigationAction.request.url, redirectedUrl.host == AppConfig.redirectHost {
// extracting token from url
let deezerToken = DeezerURLBuilder.deezerToken(fromUrl: redirectedUrl)
// saving token
PrefUtils.shared.deezerToken = deezerToken
didLogin = true
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
I don't want to go to the redirect url because i'm in a iOS app and i hope i could prevent the server step.
I have noticed that the redirectedUrl looks like : https://MY_REDIRECT_URL/#access_token=frazeeFRT188maXzvPiCeTDEjCCbrIGGaCwlkGQra4whmp7rtJ&expires=1468
I don't understand why because from the Deezer API, i should see a code query parameter which i should put in the next request for App Authentication like this :
https://connect.deezer.com/oauth/access_token.php?app_id=MY_APP_ID&secret=MY_APP_SECRET&code=THE_MISSING_CODE
That request was sent with URLSession.shared.data.
So i was assuming that i got the final access_token and continue to request the user info with :
https://api.deezer.com/user/me?access_token=frazeeFRT188maXzvPiCeTDEjCCbrIGGaCwlkGQra4whmp7rtJ
Finally i got an error stating : "An active token must be used to query information about the current user"
I try the first request inside Safari in macOS then i was redirected to MY_REDIRECT_URL. After this i tried the request to get user info and it succeeded, i saw the json response in the Safari.
As i understand, Deezer has set cookies during the redirection in Safari. My guess is requests are completed because of the cookies and when i'm in the iOS App WKWebView is dismiss and subsequent requests are made without these.
To sum up,
why am i getting access_token without providing 'my app secret request' ?
(because i ask for it with the response_type param set to token)
How to properly do OAuth dance with Deezer API in SwiftUI/Swift App without Deezer SDK ?
PS: I didn't try OAuthSwift library as i want to keep it simple.
Thx for any help
EDIT: SOLVED
it was a typo in my url parameter... but it is fully working without a server redirect.
Related
I am receiving "This application requires a valid client certificate" message when doing an HTTP GET request using Swift for an iOS app. I am using an iPad iOS 13 for testing and when opening Safari I get a popup to select a client certificate and the server authenticates successfully.
I tried first using a WKWebView and implemented the case where the authentication method is of type NSURLAuthenticationMethodClientCertificate by following Apple's developer documentation and forums:
optional func webView(_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
But after retrieving the Distinguished Names, I queried for an identity so I can create the Credential and was unable to find one. I assume this is mostly because client certificates are accessible from Apple apps like Safari and Mail but not from my iOS app.
I then tried to use a SFSafariViewController but after I learned that I can't see the website's data after the user authenticates with the client certificate. This is from Apple's documentation:
The user's activity and interaction with SFSafariViewController are not visible to your app, which cannot access AutoFill data, browsing history, or website data.
So, with this option I was unable to transfer request data back to the iOS app.
Finally, I tried using ASWebAuthenticationSession using https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service. This opened Safari, the user can select their certificate and the web server authenticates. I got a successful callback URL on the iOS app and the Safari view gets dismissed automatically. After the session has been started, I used the following to open a URL:
UIApplication.shared.open(url, options: [:], completionHandler: nil)
It opens the specified url using Safari without requesting the user to be authenticated again. This tells me the ASWebAuthenticationSession was successful. However, I am unable to send this data back to the iOS app. When using a URLSession to do an HTTP request, I get the message that it needs a valid certificate.
I am hoping there is a way from an iOS app to prompt the user for the client certificate (it can be using Safari) and then be able to do HTTP requests after the user has been authenticated on the web server. Is there a way to achieve this without having the .p12 file imported on the keychain? Any suggestions would be appreciated. Thanks!
I have working Swift code that opens an SFSafariViewController at the following URL:
https://api.imgur.com/oauth2/authorize?client_id=\(CLIENT_ID)&response_type=token&state=myState
to retreive a user token from Imgur.
With this, the user can upload photos to his personal account.As this is going to be a commercial App, I registered an App on Mashape and changed my URLs in the code to use that endpoint:
like written here
My problem is the authentication. Anonymous uploads work perfectly as I put the X-Mashape-Key in the request header correctly.
But the presented Safari window is just initialized with a URL:
let url = NSURL(string: "https://imgur-apiv3.p.mashape.com/oauth2/authorize?client_id=\(CLIENT_ID)&response_type=token&state=myState")
svc = SFSafariViewController(url: url as! URL)
svc!.delegate = self
self.present(svc!, animated: true, completion: nil)
so I don't get where to tell it the Mashape key or if it's not required, what is then.
Do I maybe need to change the CLIENT_ID? Currently it's still the one I had gotten from Imgur and Mashape doesn't seem to have sth like this. There's only the API keys.
Any help is appreciated, thank you in advance!
EDIT:
I changed the authentication URL back to the original one from Imgur and using the CLIENT_ID from Imgur.
Now the images are uploaded to the user's account while showing in my Mashape quotas, which indicates everything is as expected.
I'm not sure if this is perfectly correct as the abovementioned Link tells to change the API endpoints in general to the new one.
On the other hand, authorization is not really something using an API endpoint, rather it's a webpage with a callback, so ... Not sure! That's why I ask :)
I'm currently trying to implement GitHub Authentication via Firebase in an iOS app.
I've read through the docs and figured out what I have to do. I'm having trouble though, in implementing the communication between my app and the WebView where I authorize the application to get user's data. I currently have this code:
let url = urlComponents.url! // https://github.com/login/oauth/authorize + scope
// Not quite sure if I should use open(_:options:completionHandler:) to handle this operation.
guard UIApplication.shared.canOpenURL(url) else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
What this code does is bring the user to the browser with the GitHub authorization screen, type the password and then a blank screen shows up. Inspecting the URL in this blank screen, I've found out that it contains the parameter it should have, but I'm not quite sure how to pass this parameter to my code so I can proceed with the authentication.
Firebase doc says I should implement a Custom URL scheme to handle the OAuth callback, but I'm not sure how to do it.
Solved, solution was to edit GitHub's Authorization callback URL to have my custom URL scheme and then proceed through the documentation flow.
I'm currently working on an iOS app which will (if I can figure out this problem) use Azure as backend. The user is supposed to login with their iOS account which they already setup on their iOS device. I than use reverse authentication (https://dev.twitter.com/docs/ios/using-reverse-auth) to get the user's access token and I would like to use said access token to login the user.
I tried using (Swift snippet)
let tokenDictionary = ["access_token": "<token-I-got>"];
client.loginWithProvider("twitter", token: tokenDictionary.bridgeToObjectiveC(), completion: {(user: MSUser!, error: NSError?) in
if let user = user? {
print(user.userId)
} else if let error = error? {
print(error)
}
})
but the only thing the API returns is:
POST of Twitter token is not supported.
Any ideas how I could get this to work or do I have to switch away from Azure to something different? (And using the webview for login is not an option, as we have this nice already accounts on iOS already setup with the credentials).
Thanks for helping.
This feature is not currently supported by Azure Mobile Services. You can upvote the feature request here.
I'm trying to implement ShareKit in my app; in the SHKConfig.h file, in the section where the Twitter applications settings are required, there is a line where I'm supposed to set the Callback URL:
I have opened a Twitter application on Twitter and filled all the fields there, but I'm not clear regarding to what data should be inserted in the Callback URL field:
Can anyone explain?
The callback parameter you write in your application settings in Twitter is ignored, you can write anything, example: http://www.google.com (anything will do since it is ignored).
When you add a callback url in the #define, its value will be sent to twitter in the owner authorization step, and will override the value that you previously wrote in the Twitter website. Weird, I know. It's related to this security vulnerability.
The callback parameter is the URL Twitter is going to send the user after authentication. When running in websites instead applications, the URL callback is used to recover control of the OAuth flow.
On Applications, you can set it to a custom scheme like myapplication://twitter and then register the scheme myapplication in your app. This way, after authentication, the Twitter website running in UIWebView or Safari launches that URL, which iOS knows is assigned to your app, and that's how you recover control of the OAuth flow.
That's the theory, I don't know exactly how ShareKit works. It may be that it runs the authentication on a UIWebView and detects the activity of the user to recover control manually, which is another way to do it.
I'm using new version of ShareKit and in sources there is this comment about callback for twitter:
Callback URL' should match whatever you enter in
SHKTwitterCallbackUrl. The callback url doesn't have to be an actual
existing url. The user will never get to it because ShareKit
intercepts it before the user is redirected. It just needs to match.
I set in twitter settings callback url as http://somecallbackurl.com, set this same in sources and it works like a charm! :]. Hope this help.
You can use this
func application(_ application:UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool {
print("called")
let directedByTWTR = Twitter.sharedInstance().application(application, open: url, options: options)
return directedByTWTR
}