I am trying to add to my app VK authorization with Firebase SDK.
When user authorization finished, I try to pass token to Firebase.
func vkSdkAccessAuthorizationFinishedWithResult(result: VKAuthorizationResult!){
let tokenString = result.token.description
FIRAuth.auth()?.signInWithCustomToken(tokenString) { (user, error) in
// ...
}
}
Error: [1] (null) "NSLocalizedDescription" : "The custom token format is incorrect. Please check the documentation."
Can I use Firebase with custom auth without running server?
From Firebase Doc. Create custom tokens using the Firebase SDK,
I would say that you need to use createCustomToken() method for this.. you can not use your VK servers token to signIn with firebase ... you need to generate token for firebase with createCustomToken() method.
var uid = "some-uid";
var customToken = firebase.auth().createCustomToken(uid);
May this work for you
Related
I've been working with the Amplify SDK to get federatedSignIn working with my iOS app with "Sign in with Apple" and Cognito to eventually make calls to API Gateway / Lambda functions.
TL;DR : My access token does not appear to be "automatically included in outbound requests" to my API as per the last paragraph of this section of the docs : Cognito User pool authorization
I have successfully authenticated using the tutorial found here Authentication Getting Started and other various Youtube videos on the Amazon Web Services channel.
Upon successful sign in through Apple I'm given an ASAuthorizationAppleIDCredential object. This contains the user field (token) which I pass to the Amplify.Auth class using the following Swift code :
func signIn (with userId: String)
{
guard
let plugin = try? Amplify.Auth.getPlugin(for: AWSCognitoAuthPlugin().key),
let authPlugin = plugin as? AWSCognitoAuthPlugin,
case .awsMobileClient (let client) = authPlugin.getEscapeHatch()
else
{
return
}
client.federatedSignIn(providerName: AuthProvider.signInWithApple.rawValue, token: userId) { (state, error) in
if let unwrappedError = error
{
print (unwrappedError)
}
else if let unwrappedState = state
{
print ("Successful federated sign in:", unwrappedState)
}
}
}
All appears to be successful and to double check I use the following bit of code to ensure I'm authorized :
func getCredentialsState (for userId:String)
{
let provider = ASAuthorizationAppleIDProvider()
provider.getCredentialState(forUserID: userId) { (credentialsState, error) in
if let unwrappedError = error
{
print (unwrappedError)
}
switch credentialsState
{
case .authorized:
print ("User Authorized")
case .notFound, .revoked:
print ("User Unauthenticated")
case .transferred:
print ("User Needs Transfer")
#unknown default:
print ("User Handle new use cases")
}
}
}
In the console I see "User Authorized" so everything appears to be working well.
However when I then go to make a call to Amplify.API.post I get the following error:
[Amplify] AWSMobileClient Event listener - signedOutFederatedTokensInvalid
Failed APIError: Failed to retrieve authorization token.
Caused by:
AuthError: Session expired could not fetch cognito tokens
Recovery suggestion: Invoke Auth.signIn to re-authenticate the user
My function for doing the POST is as follows :
func postTest ()
{
let message = #"{'message": "my Test"}"#
let request = RESTRequest (path: "/test", body: message.data(using: .utf8))
Amplify.API.post (request:request)
{
result in switch result
{
case .success(let data):
let str = String (decoding: data, as: UTF8.self)
print ("Success \(str)")
case .failure(let apiError):
print ("Failed", apiError)
}
}
}`
I then went into the API Gateway UI and changed the generated Method Request on my resource from AWS IAM to my Cognito User Pool Authorizer thinking this was the issue. I also changed the awsAPIPlugin authorizationType to "AMAZON_COGNITO_USER_POOLS" in my amplifyconfiguration.json file. This unfortunately did not have any affect.
I've seen posts such as this issue User is not created in Cognito User pool for users logging in with Google federated login #1937 where people discuss the problem of having to to use a web ui to bring up the social sign in. I understand that Apple will reject your app sometimes for this. Therefore this is not a solution.
I then found this post which seems to resolve the issue however this appears to use the old version of the SDK? Get JWT Token using federatedSignIn #1276
I'm not great with Swift (I'm still an Objective C expert, but am slowly learning Swift) so I'm uncertain which path to go here and whether this is actually a solution? It does seem to be quite more complicated than the function I have that does my POST? The RESTRequest does seem to be a simple and easy solution but I'm uncertain how to pass it the Authorization token (or even how to get the token if it is needed here).
However, everything I've read about the SDK is that the authorization should be handled automatically in the background according the docs in my first link above. Specifically pointed out, again, here : Cognito User pool authorization. The last paragraph here states 👍
With this configuration, your access token will automatically be included in outbound requests to your API, as an Authorization header.
Therefore, what am I missing here as this does not appear to automatically include my access token to my outbound requests to my API?
I try to integrate google drive into my app to list mp3, m4a music files. Now I have made Google sign working, means I could signIn and signOut google account.
But when I follow google's api doc to this step Make an API call with fresh tokens, I got above error on line let authorizer = authentication.fetcherAuthorizer(). This function fetcherAuthorizer is not found.
I think maybe this doc is not up to date with latest google sdk. So I did a few search on Google...then it appears there is really rare stuff about this topic. What I found is all used this same code authentication.fetcherAuthorizer().
Thus, guys. Is there any update about this code?
user.authentication.do { authentication, error in
guard error == nil else { return }
guard let authentication = authentication else { return }
// Get the access token to attach it to a REST or gRPC request.
let accessToken = authentication.accessToken
// Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
// use with GTMAppAuth and the Google APIs client library.
let authorizer = authentication.fetcherAuthorizer()
}
Today, I find the answer in this thread googlesignin-ios
The reason is Swift cannot find the fetcherAuthorizer from Objective-C library, we must manually import it import GTMSessionFetcher.
I implemented firebase/auth and use that to sign into firebase using a custom token that I get from our API.
Auth.auth().signIn(withCustomToken: result.data.token) { (authResult, error) in
completion(authResult != nil && error == nil)
}
Then I subscribe to my document using a snapshotListener.
guard let user = Auth.auth().currentUser else {
return
}
listListener = firestoreDB.collection(shoppingListCollectionName).document(user.uid).addSnapshotListener { (documentSnapshot, _) in ....
The listener works for roughly 1 hour and then it stops working. In the logs I get:
Stream error: 'Unauthenticated: Missing or invalid authentication.'
And then I get spammed with:
Stream error: 'Unknown: An internal error has occurred, print and inspect the error details for more information.'
I don't know much the about custom token as you are using custom token to authenticate. But if we are coming to the firebase authentication, the id token issued by firebase has a lifespan of a maximum of one hour. After that the firebase will issue a new id token using the refresh token. I think your id token is getting expired and it is not getting issued again.
The Firebase ID tokens last for only one hour. As you are using a custom token, if you want stay authenticated beyond one hour you will need to use the Firebase Auth REST API. So you will have to make an HTTP request to get an ID token and a refresh token from your custom token (check the Exchange custom token for an ID and refresh token section). Then, you will just have to refresh the ID token every time it expires (check the Exchange a refresh token for an ID token section).
I just want to implement only get stuff from getstream.io in iOS application
Client.config = .init(apiKey: "<KEY>", appId: "<ID>", token: "<TOKEN>")
after writing this line of code
let timeline = Client.shared.flatFeed(feedSlug: "timeline", userId: "34")
timeline.get { (response) in
log(response)
}
I am getting 403
Basically I want to get timeline from getstream but I am not able to understand what is token in this case?
you need to generate your auth token serverside and pass that back to the iOS client.
I'm trying to setup Google Sign in for both my Android and iOS app.
The Google login is configured in the apps and should send the id token retrieved in the app to the server. The PHP code on serverside should then use the Google Client to verify the Id token that is sent using the following code:
$client = new Google_Client(['client_id' => $CLIENT_ID]);
try{
$payload = $client->verifyIdToken($request["idToken"]);
} catch(Exception $e){
api_error("ID verification failed E1; ".$e->getMessage(), 304);
}
if($payload) {
$sid = "G".$payload['sub'];
} else {
api_error("ID verification failed E2;", 304);
}
However, while this code verifies the idtoken sent by me Android app successfully it fails when sending the idtoken from the iOS app. The payload variable returns null and always reaches the ID verification failed E2 part of the code.
Debugging the idtoken that is sent from the mobile devices in the REST api endpoint https://www.googleapis.com/oauth2/v3/tokeninfo?id_token= gives me a successfull response for both Android and iOS. The only difference I can discover in the response is the azp and aud values. Given the apps use different client ids I assume this difference is as expected.
On the Android code the Google SDK has the requestIdToken(webClientId) method which allows you to set the web client id variable in order to request the id token. For the iOS Google Sign In I cannot find the option to set the web client id. I tried to set the webClientId in as the serverClientId in the GIDSignIn.sharedInstance() but this gives me a 400 error telling me the audience is invalid.
Is there a way to set this webclientid and is there a requestIdToken equivalent for iOS? I'm currently using the following code to obtain the idtoken on iOS:
#IBOutlet weak var googLoginButton: GIDSignInButton!
#IBOutlet weak var fbLoginButton: FBSDKLoginButton!
let tokenValidation = TokenValidation();
var isShown = false;
override func viewDidLoad() {
super.viewDidLoad()
fbLoginButton.delegate = self;
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
}
The TokenValidation class is a custom class that I wrote to send the data to the server.
The ViewController has a GIDSignInButton that calls the following function:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
withError error: Error!) {
if (error == nil) {
let idToken = user.authentication.idToken
tokenValidation.setFBAccessToken(accessToken: nil);
tokenValidation.setGoogleIdToken(googleIdToken: idToken);
startTokenValidate(tokenValidation: tokenValidation);
} else {
showMessage(messageStr: error.localizedDescription);
}
}
The startTokenValidate function then calls my API endpoint to verify the token. The error variable inside the app is always nil.
Is there any way to retrieve a correct idtoken or are there any alternatives to validate the Google Sign In with the backend server?
In my case, it is because the client ID in my .env file does not match the aud value returned by the Google API when iOS token is sent. The client ID set in my .env only matches with the aud returned for Android token. I don't know the best practice for this. Maybe you need to have different API client for different platform, which is instantiated with different client ID. But my simple solution is, I just omit any argument while creating the client, like this:
$client = new \Google_Client();
Looking at the source code of Google API client, when the client ID is not set, it will skip checking the aud value. Again, there might be better and more secure way to do this but this is what I did with mine.