How to authenicate AWS Appsync in iOS (Swift) - swift

Junior developer here.
I'm trying to get AWS Appsync to work in an iOS app I'm currently building, but I cant get authentication working.
I want to replicate this Javascript code in swift, for my authenication.
Amplify.configure({
Auth: {
region: "<REGION>",
userPoolId: "<USER-POOL-ID>",
userPoolWebClientId: "<USER-POOL-WEB-CLIENT-ID>"
}
});
const client = new AWSAppSyncClient({
auth: {
jwtToken: async () =>
(await Auth.currentSession()).getIdToken().getJwtToken(),
type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS
},
disableOffline: true,
region: "<REGION>",
url:
"<ENDPOINT-URL>"
});
I have found a similar problem here:
cannot authenticate user for aws appsync with swift SDK
But he hasn't gotten an answer.
I have googled plenty but cant seem to find a solution.
Could one of you kind programer souls point me in the right direction?

AWS SDK for iOS - AppSync solves your use-case. You can check out the documentation here: https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-ios.html. You can check out the source code here: https://github.com/awslabs/aws-mobile-appsync-sdk-ios. There is a starter app which will help you onboard quickly: https://github.com/aws-samples/aws-mobile-appsync-events-starter-ios.
import UIKit
import AWSAppSync
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var appSyncClient: AWSAppSyncClient?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Set up Amazon Cognito credentials
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: CognitoIdentityRegion,
identityPoolId: CognitoIdentityPoolId)
// You can choose your database location, accessible by the SDK
let databaseURL = URL(fileURLWithPath:NSTemporaryDirectory()).appendingPathComponent(database_name)
do {
// Initialize the AWS AppSync configuration
let appSyncConfig = try AWSAppSyncClientConfiguration(url: AppSyncEndpointURL,
serviceRegion: AppSyncRegion,
credentialsProvider: credentialsProvider,
databaseURL:databaseURL)
// Initialize the AWS AppSync client
appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncConfig)
// Set id as the cache key for objects
appSyncClient?.apolloClient?.cacheKeyForObject = { $0["id"] }
} catch {
print("Error initializing appsync client. \(error)")
}
return true
}
// ... other intercept methods
}

Related

didReceiveRemoteNotification not being called on MacCatalyst

When I create a CKSubscription, didReceiveRemoteNotification gets called on iOS just fine but not on MacOS. I came across a 2015 SO thread talking about a bug and the suggested workaround was to set the notification info's soundName to an empty string - unfortunately that didn't resolve the issue for me.
Here is how I register my remote notifications:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let subscription = CKQuerySubscription(recordType: "Reminder", predicate: NSPredicate(format: "TRUEPREDICATE"), options: [.firesOnRecordCreation, .firesOnRecordUpdate])
// Here we customize the notification message
let info = CKSubscription.NotificationInfo()
info.shouldSendContentAvailable = true
info.desiredKeys = ["identifier", "title", "date"]
info.soundName = ""
subscription.notificationInfo = info
// Save the subscription to Private Database in Cloudkit
CKContainer.default().privateCloudDatabase.save(subscription, completionHandler: { subscription, error in
if error == nil {
// Subscription saved successfully
} else {
// Error occurred
}
})
}
This has to do with the bundle identifier being different on Mac Catalyst. Thanks to the soon to be introduced universal app purchase, catalyst apps can now bear the same bundle identifier as their iOS counterpart, and that fixes the issue.
Note that I was also experiencing issues with cloudkit key values not syncing on Mac (NSUbiquitousKeyValueStore). Having a single bundle id for Mac and iOS fixed the problem too.

Crashlytics - can't add custom keys, they are not caught on crash

I have a problem with crashlitycs for iOS - I cant set custom keys (they are not registered online).
Everything else is working, I can record the same data in customlogs - that works perfectly, but custom keys doesn't show whatsoever.
Part of the code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
setCrashlitycsKeys()
}
internal func setCrashlitycsKeys() {
if let userId: Int64 = UserDefaultsHelper.get(for: .UserId) {
Logger.shared.log.warning("User Id: \(userId)")
Crashlytics.sharedInstance().setUserIdentifier(String(describing: userId))
Crashlytics.sharedInstance().setObjectValue(userId, forKey: "userId")
}
if let jsonString: String = UserDefaultsHelper.get(for: .InstanceModuleConfigJson) {
let instancesModuleConfigModel = InstancesModuleConfigModel(JSONString: jsonString)
if let instance = instancesModuleConfigModel?.id {
Crashlytics.sharedInstance().setObjectValue(instance, forKey: "instanceId")
Logger.shared.log.warning("Instance Id: \(instance)")
}
}
}
Logger is just a custom CLSLogv and it works perfectly -
screenshot for log
while theres nothing in keys
screenshot no keys
(it says that no keys found)
Any ideas what can I do or check to make this working? I've spend several hours trying different types of keys, different places and so on but nothings working.
I Use Xdode Version 11.2.1 (11B53),
pod 'Fabric', '~> 1.10.2'
pod 'Crashlytics', '~> 3.14.0'
Ok I found a bug after few hours of searching, in my project I have few targets (mainApp, AppCommon etc) - project is big, so I import smaller functionalities. I had to use Crashlytics pod in 2 of them and that caused an error

How do I get an access token for Firebase Authentication?

I'm using Firebase and FirebaseUI in my project. I want to give the user an options to delete his account, but if the user has been in the app longer than 5 minutes I need to reauthenticate again.
I'm not sure how to fill these parameters in the following method:
+ (FIRAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(NSString *)accessToken;
With the credentials I can call
- (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *) credential
completion:(nullable FIRAuthDataResultCallback) completion
I know the ProviderId from:
Auth.auth().currentUser.providerID
But how do I get the access token?
You can call this function and get the Token!
Swift Code:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
}

Determine login type using AWS Cognito during resume session (Swift)

I'm having a hard time trying to figure out how to determine the login type during a resume session using AWS Cognito. My code is based upon the MobileHub sample (below).
I've integrated a name/password mode for user pools (account creation and login) as well as as a Facebook login button which all works perfectly.
I have some logic in my application that needs to behave differently depending on the login type but I can't figure out how to do it.
Anyone done this?
func didFinishLaunching(_ application: UIApplication, withOptions launchOptions: [AnyHashable: Any]?) -> Bool {
print("didFinishLaunching:")
// Register the sign in provider instances with their unique identifier
AWSSignInManager.sharedInstance().register(signInProvider: AWSFacebookSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(FacebookIdentityProfile.sharedInstance(), forProviderKey: AWSFacebookSignInProvider.sharedInstance().identityProviderName)
AWSSignInManager.sharedInstance().register(signInProvider: AWSCognitoUserPoolsSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(UserPoolsIdentityProfile.sharedInstance(), forProviderKey: AWSCognitoUserPoolsSignInProvider.sharedInstance().identityProviderName)
setupAPIGateway()
setupS3()
let didFinishLaunching: Bool = AWSSignInManager.sharedInstance().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
if (!isInitialized) {
AWSSignInManager.sharedInstance().resumeSession(completionHandler: { (result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
print("didFinishLaunching Result: \(String(describing: result)) AuthState: \(authState) \n Error:\(String(describing: error))")
if authState == .authenticated {
// Facebook or Cognito???
AWSCognitoUserAuthHelper.getCurrentUserAttribute(name: "sub", completionHandler: { (userid) in
// we need to fetch the user
ObjectManager.instance.getUser(userid: userid, completionHandler: { (user) in
ObjectManager.instance.setCurrentUser(user: user)
})
})
}
}) // If you get an EXC_BAD_ACCESS here in iOS Simulator, then do Simulator -> "Reset Content and Settings..."
// This will clear bad auth tokens stored by other apps with the same bundle ID.
isInitialized = true
}
return didFinishLaunching
}
One solution I found was to cast to the different identity profile types such as the following:
let identityManager = AWSIdentityManager.default()
if let fbIdentityProfile = identityManager.identityProfile as? FacebookIdentityProfile {
print("didFinishLaunching - Facebook login")
} else if let upIdentityProfile = identityManager.identityProfile as? UserPoolsIdentityProfile {
print("didFinishLaunching - User Pools login")
}
I can model logic in my application around this. Not sure if there is a cleaner approach using the MobileHub helper classes or AWS APIs but this works.

iOS: cannot request authorization from Spotify app

I'm developping app using spotify-iOS-SDK, i have succesfully connect my app to Spotify from Safari, but when i try to connect my app from Spotify App, it doesn't request authorization in spotify app, instead it throw me back to my app after a checkmark icon show in Spotify and it caused crash to my app because the session is null.
This is my code:
var auth = SPTAuth.defaultInstance()!
auth.redirectURL = URL(string: ENV.SPOTIFY_REDIRECT_URL
auth.clientID = ENV.SPOTIFY_CLIENT_ID
auth.requestedScopes = [SPTAuthStreamingScope, SPTAuthPlaylistReadPrivateScope,
SPTAuthPlaylistModifyPublicScope, SPTAuthPlaylistModifyPrivateScope]
if SPTAuth.supportsApplicationAuthentication(){
UIApplication.shared.openURL(auth.spotifyAppAuthenticationURL())
}else{
if UIApplication.shared.openURL(auth.spotifyWebAuthenticationURL()){
if auth.canHandle(auth.redirectURL) {
// To do - build in error handling
}
}
}
I have put spotify-action in my LSApplicationQueriesSchemes. What am i doing wrong here? I saw DemoProject from https://github.com/spotify/ios-sdk
and it worked. It should request authorization right after my app go to Spotify App
You need some code in your AppDelegate that looks like follows:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let auth = SPTAuth()
if auth.canHandle(auth.redirectURL) {
auth.handleAuthCallback(withTriggeredAuthURL: url, callback: { (error, session) in
// Do other things to save session...
return true
}
return false
}
i have resolved my issues, the problem is my Bundle ID in my app is different from my BundleID in my Spotify Dashboard.
https://developer.spotify.com/my-applications
Just match my bundle ID and it worked!