Authentication Services

RSS for tag

Improve the experience of users when they enter credentials to establish their identity using Authentication Services.

Authentication Services Documentation

Posts under Authentication Services tag

71 Posts
Sort by:
Post not yet marked as solved
1 Replies
338 Views
I have a SwiftUI app live on the App Store which uses ASWebAuthenticationSession to authenticate against several remote services. It all runs perfectly on iOS but I'm getting a stream of complaints from users running it on Monterey / Catalyst. There seem to be 2 main errors: The auth browser window doesn't anchor properly, so the window will pop-up but it's completely independent of my app, so can easily end-up behind my application (which then appears to have hung) Even worse, on some machines (mostly m1 iMacs) the window doesn't pop-up at all but the OAuth request to the browser sits in some queue somewhere and at a later point when the user happens to restart their browser they will be prompted to login for every single time they clicked on the "sign in" button in my app. I've seen lots of other reports of the 2nd problem which just seems to happen randomly so I don't have a repro. I've seen a similar number of different ways of implementing ASWebAuthenticationPresentationContextProviding which (I presume) ought to fix the former. Unfortunately none of them work. I'm including some minimal code to reproduce the former issue. This is my own amalgamation of several other approaches. It doesn't work - if you click on the "sign in" button the OAuth window will pop-up but it's completely independent and you can easily move the "anchor" window on top of it. Has anyone managed to get this working? Here's the code: import SwiftUI import AuthenticationServices import UIKit struct SignInView: View {     @StateObject var viewModel = SignInViewModel()     @State var window: UIWindow? = nil     var body: some View {         VStack(spacing: 16) {             Image(systemName: "person.circle")                 .resizable()                 .frame(width: 50, height: 50)                 .foregroundColor(.primary)             VStack(spacing: 8) {                 Text("You must be log in to proceed any further")                     .foregroundColor(.secondary)                     .font(.title3)                     .multilineTextAlignment(.center)                     .padding()                 Button {                     viewModel.signIn(window: self.window)                 } label: {                     Text("Sign In")                         .foregroundColor(.white)                         .padding()                         .clipShape(RoundedRectangle(cornerRadius: 8))                         .background(                                     HostingWindowFinder { window in                                         self.window = window                                    }                         )                 }             }         }     } } class SignInViewModel: NSObject, ObservableObject, ASWebAuthenticationPresentationContextProviding {     var window: UIWindow? = nil     func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {         return window ?? ASPresentationAnchor()     }     func signIn(window: UIWindow?) {         self.window = window         let authSession = ASWebAuthenticationSession(url: URL(string: "https://accounts.spotify.com/authorize")!, callbackURLScheme: "myapp-auth") { (url, error) in             if let error = error {                 print(error.localizedDescription)             } else if let url = url {                 print(url.absoluteString)             }         }         authSession.presentationContextProvider = self         authSession.prefersEphemeralWebBrowserSession = true         authSession.start()     } } struct HostingWindowFinder: UIViewRepresentable {     var callback: (UIWindow?) -> ()     func makeUIView(context: Context) -> UIView {         let view = UIView()         DispatchQueue.main.async { [weak view] in             self.callback(view?.window)         }         return view     }     func updateUIView(_ uiView: UIView, context: Context) {     } }
Posted
by dutton.
Last updated
.
Post not yet marked as solved
4 Replies
889 Views
I'm trying to deprecate iOS 13 from my app. One of the compilation warnings I got as a result was: 'SecRequestSharedWebCredential' is deprecated: first deprecated in iOS 14.0 - Use ASAuthorizationController to make an ASAuthorizationPasswordRequest (AuthenticationServices framework) So I tried updating my code as follows let provider = ASAuthorizationPasswordProvider()             let request = provider.createRequest()             let authorizationController = ASAuthorizationController(authorizationRequests: [request])             authorizationController.delegate = self             authorizationController.presentationContextProvider = self             authorizationController.performRequests() But it always calls the delegate callback func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) with error Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1001 "No credentials available for login." UserInfo={NSLocalizedFailureReason=No credentials available for login.} Even though the device (or simulator) has a stored password for my website. I have my website as an "associated domain" for my app of type webcredentials. What am I doing wrong here?
Posted
by tracyk.
Last updated
.
Post not yet marked as solved
1 Replies
231 Views
Hello, I'm writing a small app which requires user accounts and authenticating against a remote backend (REST API) which belongs to the app. What I've done so far, is adding the "Sign in with Apple" button to my SwiftUI and receiving a ASAuthorization object containing user, IdToken, AuthCode, ... When a user signs in the first time, I have to create an account in the backend, saving the userId and Name. This and all future calls to my backend API I want to secure by using the IdToken as Bearer for Authentication. My backend will verify the token as described here. For me, it's not clear how to refresh the IdToken in my App without asking the user again for his sign in (like the button does). Or what should I save on the users' device that he has not to sign in after restarting the app. This documentation saves the userid in the Keychain and tries to get the userid again on app start - but where is the idToken / what if the idToken is expired?
Posted Last updated
.
Post not yet marked as solved
0 Replies
251 Views
Can you collect phone numbers following sign-in with apple? I am creating a firebase backed app and offering users the option to sign in with third party apps such as facebook and google. According to Apple, this means i must also include an option to sign-in with Apple; however my app is getting rejected in the review process for attempting to grab more information from the user after they authenticate with apple. I get that sign-in with apple is supposed to be a one click solution to getting the user interacting with the core of the app; however, we require the user's phone number for app functionality. Is there any way to get the app approved in this situation while still getting the user's phone number at sign-up? I do not see an option to grab the number from the sign-in with apple credential like you can for name.
Posted
by bsaggese.
Last updated
.
Post not yet marked as solved
0 Replies
307 Views
My application is linking with the customer's apple account on the front end with no problems. But I would like to validate the data when it comes to the backend. Having the userid how can I validate it in node.js? do you have any route that passes the id and returns data such as name and email? Thanks
Posted Last updated
.
Post not yet marked as solved
0 Replies
235 Views
Hi there, We are using the AuthenticationServices framework in our app to make it possible for users to sign in to their account via an OAuth2 flow. It happens sometimes that the login page, which opens in the in-app browsers via the AuthenticationServices, do not handle the CSRF token correctly resulting in that the user is unable to log in. The form will reject the POST-request since the CSRF token is incorrect. Does someone have experience with this or, even better, a solution? :-)
Posted Last updated
.
Post not yet marked as solved
5 Replies
1.5k Views
I’m trying to implement web credentials sharing on macOS 11.0. According to documentation: 1) added associated domain file to website and now it’s available at location https://my.website/.well-known/apple-app-site-association (my.website is just and example here) 2) added Associated Domains entitlement to my macOS app with value webcredentials:my.website Problems: when using SecAddSharedWebCredential func get callback error:  Error Domain=NSOSStatusErrorDomain Code=-4 "SecAddSharedWebCredentialSync not supported on this platform" (kCFMessagePortTransportError / kCSIdentityDeletedErr / unimpErr:  /  / unimplemented core routine) UserInfo={numberOfErrorsDeep=0, NSDescription=SecAddSharedWebCredentialSync not supported on this platform}) when using SecRequestSharedWebCredential func get console error and callback error (the same for ASAuthorizationController with ASAuthorizationPasswordRequest request) Authorization failed: Error Domain=AKAuthenticationError Code=-7089 Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1000 What I’m doing wrong? 
Posted
by dimaty.
Last updated
.
Post not yet marked as solved
1 Replies
339 Views
Question: Do App Clips support receiving callbacks from ASWebAuthentictionSession's redirectCallbackURL? Context: I'm trying to get CloudKit working in an app clip. Read support is done, but it would be nice for the user to see the capabilities before full download. Presently, I have the CloudKit Web Services successfully invoking redirectURL within SafariViewController, but I haven't figured out how to get it to direct to something the App Clip can get a hold of. CloudKit allows you to specify three different callbackURLs: https:// [freeform] http:// localhost[freeform] cloudkit-icloud.:// [freeform] I am new to AuthenticationSerivces framework so I may have missed something. The desired OAuth doesn't need to be CloudKit/iCloud but any provider. Everything is working except the redirect URL.
Posted
by edorphy.
Last updated
.
Post marked as solved
19 Replies
4.9k Views
In our app we're performing authentication using ASWebAuthenticationSession. SSO seems to work fine in iOS 13 for different paths for the same domain but when running the same app in iOS 14, cookies don't seem to be attached to subsequent requests once authenticated in safari window. I'm not sure if it helps : Looking at the logging in instruments when running the app in iOS 14 device, I can see : 00:09.690.903 Default iOS B2c Sample (1691) CFNetwork Default iOS B2c Sample 0x1631f Faulting in NSHTTPCookieStorage singleton 00:09.690.929 Default iOS B2c Sample (1691) CFNetwork Default iOS B2c Sample 0x1631f Faulting in CFHTTPCookieStorage singleton 00:09.690.944 Default iOS B2c Sample (1691) CFNetwork Default iOS B2c Sample 0x1631f Creating default cookie storage with default identifier (Above logs don't happen in iOS 13) and later in iOS 14: 00:10.113.701 Debug iOS B2c Sample (1691) CFNetwork Default iOS B2c Sample 0x1631c Task <88E60E41-6B7B-4787-ABF6-B65C92C8FF4E>.<1> request https://testb2c.b2clogin.com/testb2c.onmicrosoft.com/b2c_1_susi/oauth2/v2.0/token is NOT allowed to set HSTS for main doc  In iOS 13 : 00:15.570.171 Debug iOSB2C (5320) CFNetwork Default iOSB2C 0x24045d Task <79A2078B-718D-4D4D-A46D-1FF1B2238431>.<6> request n/a is NOT allowed to set HSTS for main doc  00:23.139.303 Debug iOSB2C (5320) CFNetwork Default iOSB2C 0x24045d Task <88D45825-FB1E-4C38-8EFF-87A8528B61E3>.<7> request n/a is NOT allowed to set HSTS for main doc  Has anyone noticed similar issue with ASWebAuthenticationSession?
Posted
by amepatil.
Last updated
.
Post not yet marked as solved
0 Replies
236 Views
Hi everyone, I hope you're all doing well. I was wondering what is the most secure way to communicate with a login API to which I send credentials and get Json Web Token in case of a successful login ? Also, where should I store the JWT while the app is running ? I red in the documentation that "ATS requires that HTTP connections use HTTPS", so I thought that using URLSession is a good and secure solution. I'm quite new to SwiftUI and trying to learn what is the most secure way to communicate sensitive data to web API. Thanks in advance for your answers
Posted
by aissam93.
Last updated
.
Post not yet marked as solved
0 Replies
405 Views
When I try testing the sign-in with apple button on ANY xcode simulator, it doesn't work. After inputting the password to sign in, the spinner in the password field never stops spinning and nothing from the oauth methods gets printed. I have tested the sign in on multiple real-world devices. It always works. It seems to just be simulators that are causing the issue I'm worried my app will be rejected because of this. Has anyone encountered this? Any fixes?
Posted
by willt42.
Last updated
.
Post not yet marked as solved
2 Replies
1.2k Views
I have a class where I want to handle the Sign in with Apple logic. I have created an ASAuthorizationController, set the presentationContextProvider to be my view controller and set the delegate to the class itself. When I perform the requests, the system dialog shows up. But upon canceling, my delegate method does not get called. Here is my class: final class AppleSignInProvider: NSObject { typealias CompletionHandler = (Result<AuthCredential, Error>) -> Void enum AuthError: LocalizedError { case credential case nonce case identityToken case identityTokenString } private let completion: CompletionHandler private var authorizationController: ASAuthorizationController? init(completion: @escaping CompletionHandler) { self.completion = completion } private var currentNonce: String? private func sha256(nonce: String) -> String { let inputData = Data(nonce.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { return String(format: "%02x", $0) }.joined() return hashString } func signIn(viewController: UIViewController) { let nonce = randomNonceString() currentNonce = nonce let request = ASAuthorizationAppleIDProvider().createRequest() request.requestedScopes = [ .fullName, .email ] request.nonce = sha256(nonce: nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.presentationContextProvider = viewController.view.window authorizationController.delegate = self authorizationController.performRequests() self.authorizationController = authorizationController } // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) guard errorCode == errSecSuccess else { fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)") } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result } } extension AppleSignInProvider: ASAuthorizationControllerDelegate { func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { do { guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else { throw AuthError.credential } guard let nonce = currentNonce else { throw AuthError.nonce } guard let appleIDToken = appleIDCredential.identityToken else { throw AuthError.identityToken } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { throw AuthError.identityTokenString } let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce) completion(.success(credential)) } catch { completion(.failure(error)) } } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { completion(.failure(error)) } } My delegate methods are called when the view controller is set as delegate, but that is not a fix for my issue.
Posted
by ilendemli.
Last updated
.
Post not yet marked as solved
2 Replies
746 Views
I have been trying to figure this out for like 5 hours, and I can't seem to see what its happening. My app is trying to get users signIn with using Google or Apple methods. Once they finish the SignUp with any provider, It should take them to another screen (OnboardingViewPart2) to finish the profile setup. However, the issue is that when I finish entering my email on the Google SignUp, the screen closes and the app get stuck for like 10 secs and throws the Bad Access error. My debug takes me that there is something going on with AuthService, but I can't figure out what. Firebase recognizes that the method was used, but doesn't create any Collections or Documents. Please Help :) ContentView.swift OnboardingView.swift AuthService.swift OnboardingViewPart2.swift SignInWithGoogle.swift
Posted Last updated
.
Post not yet marked as solved
0 Replies
378 Views
Is there some way to suggest to the system that it should autofill passwords in a ASWebAuthenticationSession on a domain not previously associated with my app? I'm working on an app that currently has native login and registration screens, password autofill works great and links credentials it to my associated domains. I now need to move these login and registration screens to use ASWebAuthenticationSession and have users authenticate on a website on a new domain. The system does not autofill my apps credentials on these pages. I can add this new domain as an associated domain, and new registrations are able to save the password and then autofill it later. But I can't get previously saved passwords to autofill on this new domain. Is that possible? I did manage to use Shared Web Credentials to save the users credentials against the new domain when they login. But this will only migrate users that login between now and when I switch to ASWebAuthenticationSession, not all users will be migrated. Any new ideas or solutions much appreciated.
Posted
by Ashton.
Last updated
.
Post not yet marked as solved
2 Replies
1.1k Views
Hello, I'm currently struggling to figure out how I can make Apple sign in work with my app configuration. Maybe I'm just dumb, but I really can't figure out what I need to do to make it work. So I have a Next.js app setup server-side rendering my React frontend, and on a separate server, I have a Node.js (specifically Adonis.js) backend/api which I use to handle auth and sessions. I have both Facebook and Google OAuth2 logins setup and working perfectly, where I'm receiving a code as a query param in my callback url to my frontend, which the client then sends that code to my backend/api, which uses that code with the provider (FB or Google) to get their email, name, and any other data I could use to prevent the user from having to add later, and either create the user and log them in, or just log them in if they already exist using cookies. I don't need any sort of write access to their third party account, or anything more than reading their name and email so they don't have to enter it themselves, and so they don't have to enter a password on my site. There are 2 different questions I have. (and if there is a solution to the first one, it would make my life so much easier ha..) If I use these query params similar to how I would with Google or Facebook: response_type: 'code', client_id: Env.get('APPLE_APP_ID'), redirect_uri: 'https://example.com/auth/apple/callback' state: '', scope: '', response_mode: 'query' And I get redirected back to my frontend with the code in the url params, and I send it to my API like I do with Facebook/Google, is there any endpoint with Apple's system that I can use that code to request the user's email and name from? 2. From reading through doc after doc, and it still being fuzzy, I'm thinking I may need to use the form_post response mode kind of like this?: response_type: 'code id_token', client_id: Env.get('APPLE_APP_ID'), redirect_uri: 'https://example.com/auth/apple/callback', state: '', scope: ['email', 'name'].join(' '), response_mode: 'form_post' My impression is that it would post a token, and the user data to my callback url, and that I can get the user's email and name from the user's first request and attach the token received to the user in my database. I just do not for the life of me understand how I could use this pattern with how my app is setup. Would I have to have a post handler and a page setup on the same route (I don't even know if Next.js allows something like that), and then from that, I send that data to my backend server and create the account with the data received? Even if all that worked, I don't think I would be able to set the user's session since I rely on the request being made from my frontend to my backend utilizing the set-cookie header. Please let me know your thoughts, input, or clarifications. Thanks, Brody
Posted
by brodymac.
Last updated
.
Post not yet marked as solved
0 Replies
182 Views
Hello, Our platform uses Apple ID for authentication and login, both on the web and in our native app. We have noticed that if a user logs in through the web via Apple ID and they have the iOS app installed, the app automatically opens after authentication. This is the URL that seems to open the app: https://appleid.apple.com/auth/authorize?... Is it possible to prevent this? We would like mobile web users to be able to use the mobile web site even if they do have the native app installed. Currently they are forced into the app after login. I've checked a few other apps and this behavior exists among them as well, it doesn't seem to be a quirk of our system only. Thank you! Doug
Posted
by dougp.
Last updated
.
Post not yet marked as solved
1 Replies
336 Views
Hi folks! I've been working on some UX improvements for our users and stumbled upon an issue. I extracted codes from our project into a separate project. Here's the link, so you can check it out: https://github.com/SergeyPetrachkov/ASAuthControllerIssueSample So, here's the issue: If I have both email-password and apple id records in my keychain for an app, and want to request that data to do auto-login, I can get email-password based accounts info fine. Apple ID does not work as expected though. I receive ASAuthorizationAppleIDCredential object with authorizationCode == nil. I do receive credential.identityToken and can decode the token. It's a valid one, but the thing is that I need authorizationCode. If I use stand-alone login function of AppleAuthenticator, it works correctly. ASAuthorizationController executes performRequests perfectly and I can get authorizationCode from ASAuthorizationAppleIDCredential. The issue is with AggregatedAuthenticator. It seems that ASAuthorizationController is sort of broken and cannot get all the data if there's more than one request passed to it. AggregatedAuthenticator(anchor: view.window!).startAutoLogin() // does not work with apple id but AppleAuthenticator(anchor: view.window!).login() // works The only difference is that AppleAuthenticator uses only one request in ASAuthorizationController. The only workaround that I could come up with is if I go to AggregatedAuthenticator and do the login again there, see the comment in code: public func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let appleIDCredential as ASAuthorizationAppleIDCredential: // Question: here we receive the credential without authorizationCode, but why? appleAuthenticator.login(with: appleIDCredential) // BUT if I do: // appleAuthenticator.login() // it works fine, but it shows that bottom sheet again asking for your face/touch-id again, but only for apple id this time case let emailPasswordPair as ASPasswordCredential: emailAuthenticator.login(with: emailPasswordPair) default: print("Irrelevant stuff") } } Any ideas, folks?
Posted Last updated
.
Post not yet marked as solved
0 Replies
400 Views
Hello, Apple Team. In our iOS app, we are planning to use ASWebAuthenticationSession for cookie sharing with Safari App for single sign on. Normal steps we can think of are as follows: Start ASWebAuthenticationSession. Alert dialog shows up for user permission. If the user permits, web browser shows up. A certain our web page which set cookies is loaded, and immedeiately redirect to ASWebAuthenticationSession's callbackURLScheme url without user operation. ASWebAuthenticationSession's web browser dismissed. In this case, user does nothing on the web brwoser. So if the web browser does not appear on screen, we think user experience is much better. We find out that ASWebAuthenticationSession's web browser view controller can be hidden by using presentationAnchor(for:) method of ASWebAuthenticationPresentationContextProviding protocol. In this case, only alert dialog for user permission shows up. This is very good UX for our app. But we've found following statement on SFSafariViewController document. https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller Important In accordance with App Store Review Guidelines, this view controller must be used to visibly present information to users; the controller may not be hidden or obscured by other views or layers. Additionally, an app may not use SFSafariViewController to track users without their knowledge and consent. And App Store Review Guidelines saids https://developer.apple.com/app-store/review/guidelines/ (vii) SafariViewController must be used to visibly present information to users; the controller may not be hidden or obscured by other views or layers. Additionally, an app may not use SafariViewController to track users without their knowledge and consent. ASWebAuthenticationSession document saids nothing about like this. But we would like to make clear. Are these statements applied to ASWebAuthenticationSession also? If we hide ASWebAuthenticationSession's web browser, our app will be rejected?
Posted Last updated
.