Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.

Post

Replies

Boosts

Views

Activity

Secure WS requests
Hello, I would like to secure the exchanges between my application and my webservices to make sure requests are only made by an authentic application. By searching the internet I discovered that App Attest from Device Check framework exists but it looks like there are some limitation about it : App Attest doesn't work on most App Extensions (like Share extension) We are limited by the requests count made to the App Attest webservice (only when generating the Apple certificate, one time by device / application). The problem is I need this security on my app extension because I have a Share extension sending e-mails. Do you have advice to secure the exchanges between my app and my webservices ?
2
0
231
Oct ’24
Instagram login using ASWebAuthenticationSession
I am currently using the ability to log in with my Instagram account using ASWebAuthenticationSession and it is not working! I filled in the URL directly and there was no problem on the web, but when I run it in SwiftUI in Xcode, it doesn't work and Error: The operation couldn’t be completed. (com.apple.AuthenticationServices.WebAuthenticationSession error 2.) I get this error. I was told that I need a custom scheme to return to mobile, but the Instagram redirect URL says no custom scheme. What should I do? IDs and URLs are placed under assumption. I have no idea since this is my first implementation. Should I send the scheme URL from the website to mobile once using Django or something else? import SwiftUI import AuthenticationServices struct InstagramLoginView: View { @State private var authSession: ASWebAuthenticationSession? @State private var token: String = "" @State private var showAlert: Bool = false @State private var alertMessage: String = "" var body: some View { VStack { Text("Instagram Login") .font(.largeTitle) .padding() Button(action: { startInstagramLogin() }) { Text("Login with Instagram") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } if !token.isEmpty { Text("Token: \(token)") .padding() } } .alert(isPresented: $showAlert) { Alert(title: Text("Error"), message: Text(alertMessage), dismissButton: .default(Text("OK"))) } } func startInstagramLogin() { let clientID = "XXXXXXXXXX" // Instagram client ID let redirectURI = "https://example.com" // Instagram Redirect URI guard let authURL = URL(string: "https://api.instagram.com/oauth/authorize?client_id=\(clientID)&redirect_uri=\(redirectURI)&scope=user_profile,user_media&response_type=code") else { print("Invalid URL") return } authSession = ASWebAuthenticationSession(url: authURL, callbackURLScheme: "customscheme") { callbackURL, error in if let error = error { print("Error: \(error.localizedDescription)") return } guard let callbackURL = callbackURL else { print("Invalid callback URL") return } if let code = URLComponents(string: callbackURL.absoluteString)?.queryItems?.first(where: { $0.name == "code" })?.value { print("Authorization code: \(code)") getInstagramAccessToken(authCode: code) } } authSession?.start() } func getInstagramAccessToken(authCode: String) { let tokenURL = "https://api.instagram.com/oauth/access_token" var request = URLRequest(url: URL(string: tokenURL)!) request.httpMethod = "POST" let clientID = "XXXXXXXXXXXX" let clientSecret = "XXXXXXXXXXXXXX" // Instagram clientSecret let redirectURI = "https://example.com/" let params = "client_id=\(clientID)&client_secret=\(clientSecret)&grant_type=authorization_code&redirect_uri=\(redirectURI)&code=\(authCode)" request.httpBody = params.data(using: .utf8) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error.localizedDescription)") return } guard let data = data else { print("No data") return } if let jsonResponse = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let accessToken = jsonResponse["access_token"] as? String { print("Access Token: \(accessToken)") // ここでアクセストークンを使用してInstagram APIにアクセスする } else { print("Failed to get access token") } }.resume() } } #Preview { InstagramLoginView() }
2
0
285
Oct ’24
Remove Tracking from App
Hello I have an app that uses the user's Device ID for tracking purposes. I have since removed all ads and tracking. I am now in a difficult position because I cannot turn off Device ID Tracking from App Privacy. The current app version has this on and contains the framework for turning it on. If I try to submit an app without Tracking, it gets rejected with the message "The app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 18.0." So, I am now stuck. I cannot turn off Device Tracking in App Privacy because my app previously had tracking. I cannot remove the framework for Tracking because App Privacy has tracking on. How can I proceed to remove all tracking traces from my app? Jake
0
1
324
Oct ’24
invalid_grant while token validation
Hi, I have implemented Sign in with Apple on Android four months ago, and it work perfectly. We are using React Native with expo, using expo-auth-session and firebase function to get code back to start the token validation process. However, recently we start to receive invalid_grant with no error description while token validation, however the same client secret works on firestore without issue, which confuses us. According to https://developer.apple.com/documentation/technotes/tn3107-resolving-sign-in-with-apple-response-errors, the common reasons that I receive invalid_grant are: The client_id does not match the client for which the code was issued. The code has expired or has been previously consumed by the validation server. Is there any way I could differentiate whether is client_secret wrong or the code was used or any other reasons?
2
4
382
Oct ’24
Sign in with Apple user ID after App Store transfer
Hello, Following a company split we are planning to transfer one of our apps, which has Sign in With Apple enabled, to another team. We want to provide a smooth migration experience for the users by minimizing downtime and avoiding the duplication of accounts in our database. In our backend we generate a client secret using the transferring team’s ID. We then use this client secret with the “https://appleid.apple.com/auth/token” endpoint which returns the identity token. With the above in mind, I have the following questions: If we don’t update the team ID immediately after the transfer in our backend, will the identity token returned by the endpoint above contain the transferring team user ID in the sub field or, will it contain the recipient team user ID? Is there any possibility that we will ever receive an identity token containing a transferring team user ID in the sub field after we accept the transfer? Thanks, Bruno
1
0
204
Oct ’24
[MacOS] Determining whether user already has passkey for given domain
Hi, I'm leveraging ASAuthorizationSecurityKeyPublicKeyCredentialProvider to authenticate users to an internal service using security keys or passkeys. I'm not using Sign in with Apple - registration is done in another internal service. We're using associated domains. This is on MacOS only. I'm wondering whether I can programatically determine whether the user has a passkey enrolled with our super-secret-internal-service.com domain already? The reason I'm asking is simply better UX - if the user doesn't have a passkey enrolled, I'd like to avoid offering them an option to use a platform authenticator and only offer them to tap their security key. We can assume that all users already have their security keys enrolled already. So something like the following: let securityKeyProvider = ASAuthorizationSecurityKeyPublicKeyCredentialProvider(relyingPartyIdentifier: options.rpId) let securityKeyRequest = securityKeyProvider.createCredentialAssertionRequest(challenge: options.challenge.data(using: .utf8) ?? Data()) let platformProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: options.rpId) let platformKeyRequest = platformProvider.createCredentialAssertionRequest(challenge: options.challenge.data(using: .utf8) ?? Data()) var authRequests: [ASAuthorizationRequest] = [securityKeyRequest] if (userHasPasskeyForDomain("super-secret-internal-service.com")) { // TODO how do I check this?? authRequests.append(platformKeyRequest) } let authController = ASAuthorizationController(authorizationRequests: [platformKeyRequest, securityKeyRequest]) Many thanks!
1
1
299
Oct ’24
PSSO Extension
I'm attempting to make an alternative to the MS Company Portal app. We are looking to implement PSSO in our organization and are not satisfied with the features that Company Portal offers. One example of this is, we don't like what the password reset workflow looks like. We'd like to make it so the reset process is more fluid. Additionally, we want to report the status of the service more readily (not requiring clicking so far into System Settings to locate it). These are just a couple examples of what we're not thrilled with... In light of this, my desire is to create another app, that includes a PSSO extension that is able to connect to Entra. I have scoured the internet, developer portal, and macadmin forum... and have failed to find a comprehensive guide for helping me through this. Currently Using: IDP: Entra Language: SwiftUI Frameworks: MSAL and KeychainAccess Any help would be great... a comprehensive guide would be AMAZING!
1
0
278
Oct ’24
Sign in with Apple Credential State Failing on watchOS for Existing Users
Hello everyone, I’m encountering an issue with Sign in with Apple in my watchOS app and would appreciate any guidance. Background: Initially, I did not have the Sign in with Apple capability enabled on my watchOS app. I have since enabled the capability and grouped it with my iOS app. For new user accounts created after this change, everything works perfectly: The credentialState check returns .authorized on both iOS and watchOS. However, for existing user accounts (created before enabling the capability on watchOS): The credentialState check returns not authorized on watchOS. The check still returns .authorized on iOS for these accounts. Error Details: When calling ASAuthorizationAppleIDProvider.credentialState(forUserID:) on watchOS for existing accounts, I receive the following error: Error Domain=AKAuthenticationError Code=-7074 "(null)" My Suspicions: I believe the issue arises because the existing Sign in with Apple tokens are only associated with the iOS app’s bundle identifier and not with the watchOS app’s bundle identifier. Since the capability wasn’t enabled on the watchOS app when these accounts were created, their tokens aren’t valid for the watchOS app. Questions: Is this the correct explanation for why the credentialState check fails on watchOS for existing accounts, resulting in the AKAuthenticationError Code=-7074 error? Can I update or migrate the existing accounts so that their Sign in with Apple tokens are valid for the watchOS app as well? If so, how can this be achieved? Are there any best practices for handling this situation without requiring users to re-authenticate or removing the credentialState check from the watchOS app? Goal: I want to maintain the credentialState check on the watchOS app because it works correctly for new accounts and is important for security. I’m looking for a solution that allows existing users to continue using the app on their Apple Watch without interruption or additional sign-in steps. Any help or suggestions would be greatly appreciated! Thank you!
1
0
285
Oct ’24
Certificate exceeds maximum temporal validity period
I have code where we're evaluating SSL certificates in sec_protocol_options_set_verify_block. We have the following code: let secTrust = sec_trust_copy_ref(trust).takeRetainedValue() isValidCertificate = SecTrustEvaluateWithError(secTrust, &error) I'm getting the error that the maximum temporal validity period has been exceeded: Error Domain=NSOSStatusErrorDomain Code=-67901 "“server.com” certificate is not standards compliant" UserInfo={NSLocalizedDescription=“server.com” certificate is not standards compliant, NSUnderlyingError=0x300ddd350 {Error Domain=NSOSStatusErrorDomain Code=-67901 "Certificate 0 “server.com” has errors: Certificate exceeds maximum temporal validity period;" UserInfo={NSLocalizedDescription=Certificate 0 “server.com” has errors: Certificate exceeds maximum temporal validity period;}}} When I inspect the certificate, it's valid for 394 days (4/16/2024 through 5/15/2025) and other than being a wildcard certificate, should be fully trusted. I can't find any information about this specific error. Is Apple requiring SSL certs to be less than 398 days now? Which brings me to the second part - we're OK using this to workaround it var trustFailureExceptions: CFData? = SecTrustCopyExceptions(secTrust) SecTrustSetExceptions(secTrust, trustFailureExceptions) But I haven't found anyway to be able to inspect trustFailureExceptions to ensure it only is this specific error. I'm concerned that otherwise this is going to open up validity exceptions for any certificate problem, which is definitely not what I want to do.
6
0
346
Oct ’24
AuthenticationServices framework returns an invalid signature when signing in with a passkey in a Swift app for iOS/macOS
I am trying to implement a login page in SwiftUI for an idp that relies on passkeys only, following the sample code from the food truck app. The registration of a new passkey works fine but when it comes to signing in, ASAuthorizationPlatformPublicKeyCredentialProvider().createCredentialAssertionRequest returns a signature that cannot be verified by the server. On safari (and other browsers) the signing in&up process works fine and additionally, a passkey registered from the swift app works on the web, which leads me to believe there is an issue in the AuthenticationServices framework as every other steps works without any problem. The verification of the signature happens on the server side (after several validation steps of the other parameters) with WebCrypto.subtle.verify(verifyAlgorithm, key, signature, data); With the data argument being a concat of the clientDataJSON and the authenticatorData and for an apple authenticator, the key argument (which is the public key stored by the server) is an EC2 key with the following verifyAlgorithm argument: verifyAlgorithm = { name: 'ECDSA', hash: { name: SHA-256 }, }; After carefully analyzing multiple responses, coming both from the app and safari, either on iOS or macOS, I can safely say that the ASAuthorizationResult.passkeyAssertion returns the expected values for: rawAuthenticatorData rawClientDataJSON credentialID userID Which all match the expected values during the server-side validation. The only remaining value from the ASAuthorizationResult.passkeyAssertion is the signature, which as mentioned above, is invalid when verified by the server. I already submitted a bug report (FB15113372) as well as a DTS request, but haven’t received any feedback yet. In order to further narrow down the problem, I replicated the signature verification process in a sage notebook. I got the same result: the signature produced in Safari is fine, but the one from the Swift app is invalid. I collected some thoughts of potential issues in this notebook, but I still haven’t been able to draw a clear conclusion on why does this issue occur. Hence if anyone has knowledge of this issue or has a similar problem with signature verification, their advice is most welcomed. Thank you in advance for your help PS: All the recent tests were made on the latest publicly available OS releases (iOS 18.01, macOS 15.0.1) and Xcode 16.0
2
0
345
Oct ’24
How to migrate macOS keychain entry to new rewritten app?
I'm working on replacing an AppKit-based Mac app with one built on Catalyst, and the Catalyst app doesn't seem to be able to read the keychain item that was saved by the old app. Both apps are using the same bundle ID. The old app uses the old SecKeychain APIs - SecKeychainFindGenericPassword and friends - and the Catalyst app uses the newer SecItemCopyMatching and such. When I try using the new API in the old app to search for the entry, it works, but the exact same code in Catalyst fails. Here's how I save an item in the old app: NSString *strItemId = @"my_item_id; NSString *username = @"user"; const char *userPointer = [username UTF8String]; NSString *password = @"password"; const char *pwPointer = [password UTF8String]; SecKeychainItemRef ref = NULL; OSStatus status = SecKeychainFindGenericPassword(0, (UInt32)strlen(strItemId.UTF8String), strItemId.UTF8String, 0, NULL, NULL, NULL, &ref); if (status == errSecSuccess && ref != NULL) { //update existing item SecKeychainAttribute attr; attr.length = (UInt32)strlen(userPointer); attr.data = (void *)userPointer; attr.tag = kSecAccountItemAttr; SecKeychainAttributeList list; list.count = 1; list.attr = &attr; OSStatus writeStatus = SecKeychainItemModifyAttributesAndData(ref, &list, (UInt32)strlen(pwPointer), pwPointer); } else { status = SecKeychainAddGenericPassword(NULL, (UInt32)strlen(strItemId.UTF8String), strItemId.UTF8String, (UInt32)strlen(userPointer), userPointer, (UInt32)strlen(pwPointer), pwPointer, NULL); } And here's the query code that works in the old app but returns errSecItemNotFound in Catalyst: NSMutableDictionary *queryDict = [[[NSMutableDictionary alloc]init]autorelease]; [queryDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; [queryDict setObject:(@"my_item_id") forKey:(__bridge id)kSecAttrService]; [queryDict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; [queryDict setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; CFMutableDictionaryRef outDictionary = nil; OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)queryDict, (CFTypeRef *)&outDictionary); I tried creating a new blank AppKit-based Mac app project in Xcode and gave it the old Mac app's bundle ID, and the SecItemCopyMatching query code above works there. Then I created a new iOS target with Catalyst enabled, also with the same bundle ID, and the query code running there under Catalyst returned errSecItemNotFound. So maybe the issue is something specific to Catalyst? Is there something I need to do with the Catalyst app to give it access to the old app's keychain entry, besides setting its bundle ID to match the old app?
1
0
397
Oct ’24
What I will receive as part of deep linking in case of Apple Pay In-app verification?
In the case of YellowFlow with In-App verification, I understand we have to configure the Launch URL (deep linking) in the PNO portal to open the app from Wallet and proceed with In-App Verification. How do we identify or retrieve information about the card the user tries to verify from the wallet when the app is opened through deep linking? I understand we can query for all secure passes and get the pass activation state to see if any of the passes require activation, How can I verify this is the card the user is trying to activate from the wallet app? What information can I receive from the PassKit SDK that I can send to the backend to identify, resolve, and activate the card?
1
0
365
Oct ’24
Using special character as password for keychain via security
I am trying to set up a KeyChain password using the security in my macOS terminal, and it happens that the special characters are encoded and not set to the keychain as it is rather encoded.. When I run this security add-generic-password -a comp -s example -w 'ã!¼àÁu' -T "" There will be no error but when the password is called back it is encoded with the something like below c3a321c2bcc3a0c38175 Does anybody know how i can achieve using this kind of characters without security encoding it as it currently does?
2
0
242
Oct ’24
Validating information sent by “Sign in With Apple”
So I’m (extremely) new to developing for iOS, and I’m looking to implement the “Sign in With Apple“ feature for an application that interacts with a server I’ve built. Following the guide I’m able to get a user’s email and name. When I send that information to my server to create a user account, do I need to do anything else (like validating that the email is actually associated with an Apple account or that the user actually owns it, etc)? I looked at the Sign in With Apple from the web article and it doesn’t seem like it’s relevant to my use case. Is it standard practice to just trust the client in the iOS world?
1
0
262
Oct ’24