Identity server Authentication is not working in iOS - ios

I am trying to login using identity server but it showing 404 page after authentication
Here is the swift code i tried
let issuer = URL(string: "https://iq.app.com/coreidentityserver")!
// discovers endpoints
OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in
guard let config = configuration else {
print("Error retrieving discovery document: \(error?.localizedDescription ?? "Unknown error")")
return
}
let request = OIDAuthorizationRequest.init(configuration: config,
clientId: "1111-1111-1111-1111-1111111",
clientSecret: "11111-1111-1111-1111-11111111",
scopes: ["openid", "profile"],
redirectURL: URL(string: "https://com.app.mobile/auth.html")!,
responseType: OIDResponseTypeCode,
additionalParameters: nil)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
print("auth state",authState)
print("auth error",error)
}
print("items")
// perform the auth request...
}

Related

Refreshing auth token with AppAuth library on iOS

I'm using the AppAuth library to get an access token for the Gmail API. I've successfully been able to create an Auth Session, and use the retrieved token to later fetch the emails.
In my AppDelegate I have two variables:
var currentAuthorizationFlow: OIDExternalUserAgentSession?
var authState: OIDAuthState?
In my SignInViewController, I have the following code for performing the authorization flow:
#objc func startAuthFlow() {
Analytics.logEvent("auth_started", parameters: nil)
let authorizationEndpoint = URL(string: "https://accounts.google.com/o/oauth2/v2/auth")!
let tokenEndpoint = URL(string: "https://www.googleapis.com/oauth2/v4/token")!
let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint,
tokenEndpoint: tokenEndpoint)
let kRedirectURI: String = "com.googleusercontent.apps.someNumber:/oauthredirect";
guard let redirectURI = URL(string: kRedirectURI) else {
return
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
// builds authentication request
let request = OIDAuthorizationRequest(configuration: configuration,
clientId: "myID",
clientSecret: nil,
scopes: ["https://mail.google.com/"],
redirectURL: redirectURI,
responseType: OIDResponseTypeCode,
additionalParameters: nil)
// performs authentication request
print("Initiating authorization request with scope: \(request.scope ?? "nil")")
appDelegate.currentAuthorizationFlow =
OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
if let authState = authState {
print("Got authorization tokens. Access token: " +
"\(authState.lastTokenResponse?.accessToken ?? "nil")")
A0SimpleKeychain().setString((authState.lastTokenResponse?.accessToken)!, forKey: "auth0-user-jwt")
A0SimpleKeychain().setString((authState.lastTokenResponse?.refreshToken)!, forKey: "auth0-user-jwt-refresh")
EmailFetcher.shared.setupEmailSession(token: (authState.lastTokenResponse?.accessToken)!)
} else {
print("Authorization error: \(error?.localizedDescription ?? "Unknown error")")
}
}
}
I then successfully save the token and the refresh token.
I saw that there was a tokenRefreshRequest() method for OIDAuthState, but my understanding is that you would need to pass in the refresh token to get a new, fresh token, correct? What's the missing piece to implementing this with AppAuth?
To refresh an access token you use a 'refresh token grant' message with arguments similar to this:
let request = OIDTokenRequest(
configuration: self.metadata!,
grantType: OIDGrantTypeRefreshToken,
authorizationCode: nil,
redirectURL: nil,
clientID: self.configuration.clientId,
clientSecret: nil,
scope: nil,
refreshToken: tokenData!.refreshToken!,
codeVerifier: nil,
additionalParameters: nil)
OIDAuthorizationService.perform(request) { tokenResponse, error in ...
Note that I'm not using the AuthState class in my sample, since I wanted to store tokens encrypted in the iOS keychain, so your code may be a little different. For something to compare against, you can run the code sample from by blog:
Code Sample
Blog Post
Create an authState from auth token or directly save authstate model into key chain then access latest refresh token using below methods.
authState
authState.performAction { (accessToken, authToken, error) in
guard let err = error else {return}
print("updated refresh token is : \(accessToken)")
}

Please copy code, switch to application and paste it there but where?

I am using oAuth2.0 for reading email from my Gmail account. And here is my code
oauthswift = OAuth2Swift(
consumerKey: "242468529977-xxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
consumerSecret: "GfGVl_xxxxxxxxxxmjnAX",
authorizeUrl: "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
responseType: "code"
)
oauthswift?.allowMissingStateCheck = true
let _ = oauthswift?.authorize(
withCallbackURL: URL(string: "urn:ietf:wg:oauth:2.0:oob")!, scope: "https://www.googleapis.com/auth/gmail.metadata", state: "",
success: { credential, response, parameters in
let parameters = Dictionary<String, AnyObject>()
// Multi-part upload
print(credential)
print(response)
},
failure: { error in
print("ERROR: \(error.localizedDescription)")
}
)
but after I allow permission it is showing me this screen
and says 'Please copy this code and switch to application and paste it there.' but I don't know where to paste code.
Please Update Your code with mine one and replace secret with your key.i'm using OAuthSwift library in my project. Also Don't forgot to add URL Type Schemes in your project. and Make Role as Editor
let kClientID = ""
func doOAuthGoogle(){
let oauthswift = OAuth2Swift(
consumerKey: kClientID,
consumerSecret: "",
authorizeUrl: "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
responseType: "code"
)
// For googgle the redirect_uri should match your this syntax: your.bundle.id:/oauth2Callback
self.oauthswift = oauthswift
oauthswift.authorizeURLHandler = getURLHandler()
// in plist define a url schem with: your.bundle.id:
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "com.cearsinfotech.GmailAttachements:/oauth2Callback")!, scope: "https://www.googleapis.com/auth/gmail", state: "GMAIL",
success: { credential, response, parameters in
// self.showTokenAlert(name: "Gmail", credential: credential)
print(credential.oauthToken)
let jsonDict = try? response?.jsonObject()
print("SUCCESS: \(jsonDict)")
print(parameters)
let _ = oauthswift.client.get("https://www.googleapis.com/gmail/v3/about", success: { response in
let jsonDict:NSDictionary = try! response.jsonObject() as! NSDictionary
print("SUCCESS: \(jsonDict)")
if let arrayMessages = jsonDict.value(forKey:"messages") as? NSArray{
let dict = arrayMessages[2] as! NSDictionary
let id = dict.value(forKey: "id") as! String
let _ = oauthswift.client.get("https://www.googleapis.com/gmail/v1/users/me/messages/\(id)", success: { response in
let jsonDict:NSDictionary = try! response.jsonObject() as! NSDictionary
print("SUCCESS: \(jsonDict)")
if let payload = jsonDict.value(forKey: "payload") as? NSDictionary
{
print(payload)
if let parts = payload.value(forKey: "parts") as? NSArray
{
print(parts)
let partDict = parts[0] as! NSDictionary
if let body = partDict.value(forKey: "body") as? NSDictionary
{
print(body)
}
}
}
}, failure: { error in
print(error)
})
}
}, failure: { error in
print(error)
})
},
failure: { error in
print("ERROR: \(error.localizedDescription)")
//code=4/pYAZQTq2Y5nz0g0hZSAC4wC3AuQLzdJlW6pVjjXDFHM#
}
)
}
You must have to USE Handler Method
//MARK:- Get URL -
func getURLHandler() -> OAuthSwiftURLHandlerType {
guard let type = self.formData.data?.handlerType else {
return OAuthSwiftOpenURLExternally.sharedInstance
}
switch type {
case .external :
return OAuthSwiftOpenURLExternally.sharedInstance
case .`internal`:
if internalWebViewController.parent == nil {
self.addChildViewController(internalWebViewController)
}
return internalWebViewController
case .safari:
#if os(iOS)
if #available(iOS 9.0, *) {
let handler = SafariURLHandler(viewController: self, oauthSwift: self.oauthswift!)
handler.presentCompletion = {
print("Safari presented")
}
handler.dismissCompletion = {
print("Safari dismissed")
}
return handler
}
#endif
return OAuthSwiftOpenURLExternally.sharedInstance
}
}
Go to authorization.py (path: .../python2.7/site-packages/pygsheets/authorization.py)
Currently, the code = input('Enter the authorization code:')
change to
code = 'the code shown in the google page which ask you to copy'

AppAuth iOS Token Exchange Problems Azure AD

I built a AppAuth test app for android using an Azure AD tenant and it works ok. Now I am trying to the same with iOS (Swift 4) and failing when trying to exchange an access code for access token. No error is returned, I do get an idToken but no accessToken or refreshToken. No other errors. Not sure what is going on. Without an access token I can't query the graph. I am using Azure AD v2. Here are some pieces of my code:
func appAuthAuthorize(authConfig: AuthConfig) {
let serviceConfiguration = OIDServiceConfiguration(
authorizationEndpoint: NSURL(string: authConfig.authEndPoint)! as URL,
tokenEndpoint: NSURL(string: authConfig.tokenEndPoint)! as URL)
let request = OIDAuthorizationRequest(configuration: serviceConfiguration, clientId: authConfig.clientId, scopes: [OIDScopeOpenID, OIDScopeProfile], redirectURL: NSURL(string: authConfig.redirectUri)! as URL, responseType: OIDResponseTypeCode, additionalParameters: nil)
doAppAuthAuthorization(authRequest: request)
}
func doAppAuthAuthorization(authRequest: OIDAuthorizationRequest) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.currentAuthorizationFlow = OIDAuthorizationService.present(authRequest, presenting: self, callback: {
(authorizationResponse, error) in
if (authorizationResponse != nil) {
self.authState = OIDAuthState(authorizationResponse: authorizationResponse!)
self.logMessage(message: "Got authorization code: \(String(describing: self.authState?.lastAuthorizationResponse.authorizationCode))")
self.doTokenRequest()
} else {
self.authState = nil
self.logMessage(message: "Authorization error: \(String(describing: error?.localizedDescription))")
}
})
}
func doTokenRequest() {
let tokenExchangeRequest = authState?.lastAuthorizationResponse.tokenExchangeRequest()
OIDAuthorizationService.perform(tokenExchangeRequest!) {
tokenResponse, error in
if tokenResponse == nil{
self.logMessage(message: "Token exchange error: \(error!.localizedDescription)")
} else {
self.authState?.update(with: tokenResponse!, error: error)
self.saveState()
self.logMessage(message: "Received token response with accesToken: \(tokenResponse!.idToken!)")
self.logMessage(message: "Received token response with accesToken: \(tokenResponse!.refreshToken!)")
self.logMessage(message: "Received token response with accesToken: \(tokenResponse!.accessToken!)")
self.retrieveUserProfile()
}
self.authState?.update(with: tokenResponse, error: error)
}
}
Got the answer. The problem is that depending on the authorization server, one has to use scopes defined for that server. In the code above, I used the default OpenId scopes of OIDScopeOpenID and OIDScopeProfile. As soon as I changed this to Azure AD scope of User.Read, everything started working correctly. So here is the net change to the code in function appAuthAuthorize:
func appAuthAuthorize(authConfig: AuthConfig) {
let serviceConfiguration = OIDServiceConfiguration(
authorizationEndpoint: NSURL(string: authConfig.authEndPoint)! as URL,
tokenEndpoint: NSURL(string: authConfig.tokenEndPoint)! as URL)
let request = OIDAuthorizationRequest(configuration: serviceConfiguration, clientId: authConfig.clientId, scopes: ["User.Read"], redirectURL: NSURL(string: authConfig.redirectUri)! as URL, responseType: OIDResponseTypeCode, additionalParameters: nil)
doAppAuthAuthorization(authRequest: request)
}

OAuthSwift (1) connection

I'm trying to create a client (in a private pod) to connect to garmin API (OAuth1) and i've some problem to do it. I'm using OAuthSwift and OAuthSwiftAlamofire
First i'm trying to get all the authorization,
let oauthswift = OAuth1Swift(
consumerKey: "*****************",
consumerSecret: "****************",
requestTokenUrl: "http://connectapitest.garmin.com/oauth-service-1.0/oauth/request_token",
authorizeUrl: "http://connecttest.garmin.com/oauthConfirm",
accessTokenUrl: "http://connectapitest.garmin.com/oauth-service-1.0/oauth/access_token"
)
oauthswift.authorizeURLHandler = SafariURLHandler(viewController: self, oauthSwift: oauthswift)
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "https://www.****.co/api/v2/garminCallback")!,
success: { credential, response, parameters in
print("Success")
print(credential.oauthToken)
print(credential.oauthTokenSecret)
print(credential.oauthVerifier)
},
failure: { error in
print("Error")
print(error.localizedDescription)
})
AppDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if (url.host == "oauth-callback") {
OAuthSwift.handle(url: url)
}
return true
}
So, this part of code open the connection page of garmin in safari, i use my account mail/pwd to connect and that's all. The callback never sucess, or never fail. So i can't access to my credentials. It's like authorize(withCallBackURL...) don't wait the callBack et never get the information in the URL (like oauth-idenfitifier).
I'dont understand why, if you have an idea thank's.
I'm Sharing my Code that's working for me
// create an instance of oAuth and retain it
let oauthSwift = OAuth1Swift(
consumerKey: "*******",
consumerSecret: "*******",
requestTokenUrl: "https://connectapi.garmin.com/oauth-service/oauth/request_token",
authorizeUrl: "https://connect.garmin.com/oauthConfirm",
accessTokenUrl: "https://connectapi.garmin.com/oauth-service/oauth/access_token"
)
// add safari as authorized URL Handler
oauthSwift.authorizeURLHandler = SafariURLHandler(viewController: self, oauthSwift: oauthSwift)
// set redirection URL
guard let redirectURL = URL(string: "oauth-swift://garmin-callback") else { return }
// add callback url to authorized url
oauthSwift.addCallbackURLToAuthorizeURL = true
// authorized the request
oauthSwift.authorize(withCallbackURL: redirectURL, success: { (credentials, response, parameters) in
print(response)
}, failure: { (error) in
print(error)
})
//authorize call has been changed to below
oauthSwift.addCallbackURLToAuthorizeURL = true
oauthSwift.authorize(withCallbackURL: redirectURL) { result in
switch result {
case .success(let (req, response, res)):
print("response=", response ?? "no")
print("req=", req ?? "no")
print("res=", res ?? "no")
print("dataString=",response?.dataString())
if let secrect = res["oauth_token_secret"] as? String{
self.garminAccessTokenSecret = secrect
}
if let token = res["oauth_token"] as? String{
self.garminAccessToken = token
}
case .failure(let error):
print(error.description)
}
}

How to generate a signed POST request for Tumblr using OAuth Swift

I am trying to get a sample Tumblr client up and running. I am using the OAuth Swift library to do my OAuth.
Right now my project has one button. This button checks to see if OAuth has been authorized or not. If it is, then it is set up to post some hard coded data to a test Tumblr account I set up.
I am getting this output on the console:
Top of authorizeWithCallbackURL
OAuth successfully authorized
Request error
Server Response:
{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}
It appears that my token is accepted and an OAuth token is generated, but for some reason it is not being included in the POST request I am trying to call once I have been authorized.
This is my code with the appropriate redactions:
import UIKit
import OAuthSwift
class ViewController: UIViewController {
var session:NSURLSession!
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 postToTumblr(sender: AnyObject) {
let oauthSwift = OAuth1Swift(
consumerKey: "***",
consumerSecret: "***",
requestTokenUrl: "https://www.tumblr.com/oauth/request_token",
authorizeUrl: "https://www.tumblr.com/oauth/authorize",
accessTokenUrl: "https://www.tumblr.com/oauth/access_token"
)
oauthSwift.authorizeWithCallbackURL(NSURL(string: "tumblrsampleapp://oauth-callback")!,
success: { credential, response in
// post to Tumblr
print("OAuth successfully authorized")
// Configure NSURLSession
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
config.HTTPAdditionalHeaders = ["Authorization":credential]
self.session = NSURLSession(configuration: config)
// Post hardcoded data to Tumblr
let request = self.request("consumerSecretKey&\(credential.oauth_token_secret)")
let uploadTask = self.session.dataTaskWithRequest(request!) { (responseData, response, error) in
// Check on some response headers (if it's HTTP)
if let httpResponse = response as? NSHTTPURLResponse {
switch httpResponse.statusCode {
case 200..<300:
print("Success")
case 400..<500:
print("Request error")
case 500..<600:
print("Server error")
case let otherCode:
print("Other code: \(otherCode)")
}
}
// Do something with the response data
if let responseData = responseData,
responseString = String(data: responseData, encoding: NSUTF8StringEncoding) {
print("Server Response:")
print(responseString)
}
// Do something with the error
if let error = error {
print(error.localizedDescription)
}
}
uploadTask.resume()
}, failure: {(error:NSError!) -> Void in
self.presentAlert("Error", message: error!.localizedDescription)
})
}
func request(credential:String) -> NSURLRequest? {
guard let url = NSURL(string: "https://api.tumblr.com/v2/blog/{hostname}/post") else {return nil}
let request = NSMutableURLRequest(URL: url)
let requestData = self.buildRequestData()
request.HTTPMethod = "POST"
request.HTTPBody = requestData
let postDataLengthString = String(format:"%d", requestData.length)
let credentialString = String(format:"%d", credential)
request.setValue(postDataLengthString, forHTTPHeaderField:"Content-Length")
request.setValue(credentialString, forHTTPHeaderField: "Authorization")
return request
}
func buildRequestData() -> NSData {
// Getting these parameters from this site:
// https://www.tumblr.com/docs/en/api/v2#posting
// It looks like there are a bunch of optional paramters
let requestDictionary = [
["type":"text"],
["title": "Hello, World!"],
["body": "Hello world. This is my first post."]
]
let data = try? NSJSONSerialization.dataWithJSONObject(requestDictionary, options: NSJSONWritingOptions())
return data!
}
func presentAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
I believe the issue involves the request function not generating the header properly. I did not see anything in the Tumblr documentation saying that I need to include an authorization token with the request, so I am assuming that they are assuming I am supposed to know that.
Any insight as to what I am doing wrong would be greatly appreciated. Thanks!

Resources