How to access current firebase user from iOS Today Extension? - ios

We're building a today widget on top of our iOS app which is working with Firebase. However we're struggling to access current signed-in user from the extension. The user at the main app is anonymous so passing credentials via shared container is not an option.
The only way that I found is passing uid and generate custom token to sign in but I was hoping to find out better way to share FIRUser between my main app and app extension. What would be the best way to achieve this?

You can share data between Host App and App Extension only using App Group.
There is no way of direct communication between your Host App and App Extension.
Even though an app extension bundle is nested within its containing
app’s bundle, the running app extension and containing app have no
direct access to each other’s containers.
App Group is a shared container used by both Host App as well as App Extension. It is like UserDefaults that store key-value pairs.
So you can save your current user information in App Group from Host App and then access it in your Today Extension from the same App Group.
For more on App Groups refer to: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html

Related

Can I perform a task in Main iOS app from the app Extension?

I have an app extension for Sharing (Share Extension) and when a user selects my app to share an image, my app will send that image to a server.
The problem is that the server requires an authenticated identity (AWS Cognito) to send the object to the server. Since I cannot share Authentication from my main app to my extension and I don't want to have the user sign in every time they want to share, I'm stuck.
I can see this being done with messaging apps where a user sends a message from a share extension. I'm not sure how they achieve this. Since the user is not asked to login again in the extension, somehow the credentials are either being shared with the extension or the app is momentarily launched to perform that upload while remaining in the background (not sure this is possible).
So my question is what is the approach I should be using. Should the extension somehow be directing the main app to upload the image or should I figure a way of sharing the access tokens with the extension in a secure way and accessing them without any user action?
The solution is to setup a shared container for the app & the extension, please see "Sharing data with your containing app" section in this article: https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#:~:text=To%20enable%20data%20sharing%2C%20use,App%20to%20an%20App%20Group.

Is it possible to access File Provider of another iOS app

I'm developing an app that needs to interact with other apps (that are developed by other persons). In order to do that, I wanted to use their File Provider to read and write from that.
I know the group they're using, but I don't know the URL of the File Provider. I need a way to copy some files programmatically.
I tried:
let provider = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.app.ish.iSH")
But it just doesn't work because I don't have the App Group in my App Id.
The iOS apps are sandboxed partly to specifically prevent this kind of thing from happening. Typically we use inter application URLs to communicate between apps. On a standard (non-jailbroken) device I don't believe there's way to read another application's files when you didn't develop that other app and can't control the app group

How to share Parse login session with iOS extension?

When writing an iOS extension for an app, is it possible to share the app's current Parse login session with the iOS extension?
iOS extensions are bundled with iOS apps but run in separate containers. So when the user logged in on the app, the extension cannot access that Parse instance. If the extension logged in again, it would create an additional login session for the user.
However the extension can share a common data container with the app. So I wonder if it is possible to store the PFSession.sessionToken in the shared container and let the extension communicate with Parse Server based on that existing session without having to login?
There are two possible solutions:
A) The elegant approach
Enable local data sharing which shares persistent data between the main iOS app and its extensions.
// Enable data sharing in main app.
Parse.enableDataSharingWithApplicationGroupIdentifier("...")
// Enable data sharing in app extensions.
Parse.enableDataSharingWithApplicationGroupIdentifier("...", containingApplicaiton: "...")
Local data sharing in Parse SDKs allows you do share persistent local
data between your main application and extensions that it contains,
including Keyboard, Share/Today/Photo/Action extensions and Document
Providers.
As described in the docs.
B) The manual approach
After login in the app, store the Parse session token PFUser.current().sessionToken in an ecrypted, shared data container.
The extension can then access the session token and continue the session with PFUser.become(sessionToken:).

Authenticating a Today Widget for API access

I need to add a Today Widget/extension to an existing iOS app, which requires the user to sign in via a WKWebView.
As the extension only communicates with Apple frameworks or via openURL() back to the main app, how would I best share the authentication token stored in the main app with the Today Widget/extension, so that it can make authenticated API calls?
Can this be done with a shared keychain? Or is there another secure alternative?
It is not feasible to have the user sign in again in the Today extension UI.
You can use App Groups to share data between the main application and today widget extension. You need to activate App Group for your application and create:
UserDefaults.init(suiteName: "group.com.yourOrganization.yourApplicationName")
In the main application set your data in this UserDefaults and try to access it from within your Today Widget extension.
Use a Shared Keychain Group to store the token, as described at 14m00s in this WWDC video.

How to use same Authenticated user token between main iOS app and its Share Extension

We have the main app integrated with Firebase SDK. User sign in via main application using email, google or facebook.
Now, we have share extension implemented which ideally should share same Authentication session internally so that data can be sent on Firebase with the same user without asking him to login again through the extension.
So, does anyone know the way to share Firebase authentication session between the Main app and share extension?
Either we sent some internal call to the main app to perform Firebase stuff because it has authentication detail within it.
The main app set some token to common user defaults via app groups which will be then used by Share extension to re-authenticate automatically.
Or Firebase provide some way to do so,
I don't know what is feasible from above.
I found a method signInWithCustomToken:completion: but, it's not related to what I actually looking for.
To read and save from the same set of NSUserDefaults you need to the the following:
In your main app, select your project in the project navigator.
Select your main app target and choose the capabilities tab.
Switch on App Groups (this will communicate with the developer portal, as it is generating a set of entitlements, and relevant App Id and so
forth).
Create a new container. According to the help, it must start
with “group.”, so give it a name like “group.myapp.test”.
Select
your Today Extension target and repeat this process of switching on
app groups. Don’t create a new one, rather select this newly created
group to signify that the Today Extension is a member of the group.
Write to your NSUserDefaults:
// In this example I´m setting FirstLaunch value to true
NSUserDefaults(suiteName: "group.myapp.test")!.setBool(true, forKey: "FirstLaunch")
Read from NSUserDefaults:
// Getting the value from FirstLaunch
let firstLaunch = NSUserDefaults(suiteName: "group.myapp.test")!.boolForKey("FirstLaunch")
if !firstLaunch {
...
}

Resources