Is email authentication using id token possible? - firebase

I'm creating a POC for an iOS application that uses extension. The extension has to know if a user is authenticated. Unfortunately a containing app and an extension are separate application which means I have to keep auth state somewhere.
I don't want to store user email and password but instead a token and use it to authenticate. However trying to authenticate with the issued token and providerId (Firebase) does seems to work.
Both apps under the same Firebase project.
Main Application (Firebase ios App1):
let userDefatuls = UserDefaults(suiteName: "group.test")
userDefatuls?.set(providerId!, forKey: "providerId")
userDefatuls?.set(value!, forKey: "token")
print("Saved value to user defaults \(value!)")
userDefatuls?.synchronize()
Extension Application (Firebase ios App2):
let userDefaults = UserDefaults(suiteName: "group.test")
let token = userDefaults?.string(forKey: "token")
let providerId = userDefaults?.string(forKey: "providerId")
print("What is the provider id \(providerId)")
let credential = OAuthProvider.credential(withProviderID: providerId!, accessToken: token!)
Auth.auth().signIn(with: credential) { (user, error) in
print("********* What is the user \(user) what is the error \(error)")
}
The above renders:
What is the user nil what is the error:
Optional(Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={error_name=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information., NSUnderlyingError=0x600000447290 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={FIRAuthErrorUserInfoDeserializedResponseKey={
code = 400;
errors = (
{
domain = global;
message = "INVALID_PROVIDER_ID : Provider Id is not supported.";
reason = invalid;
}
);
message = "INVALID_PROVIDER_ID : Provider Id is not supported.";
}}}})
Do you know if the support and works? Is there something what I'm doing wrong?

You can't sign in with a Firebase ID token. What you can do is:
Create an endpoint that takes an ID token, verifies it:
https://firebase.google.com/docs/auth/admin/verify-id-tokens
and returns a custom token:
https://firebase.google.com/docs/auth/admin/create-custom-tokens
You then signInWithCustomToken in the extension.
However, this could open a vulnerability as if a short lived ID token is leaked, the attacker can exchange it for a permanent session via that endpoint.
You can only return the custom token if the auth_time on the ID token is recent. This ensure that a recently signed in user can sync their app to with the extension.

Related

How can I solve create account problem with different providers?

I have a sign in with Google:example#gmail.com
then create an account with the same email:example#gmail.com
There is a problem with two different providers
Sign in with Google (same Gmail)
Sign in with Email (same Gmail)
How Can I handle these two (When I delete the google sign-in account from Firebase Console. I can create an account with that email) Otherwise I can't create an account with that email and also can't sign in.
I learning Firebase Auth with https://github.com/gladly-team/next-firebase-auth
If you first sign in with Google using "example#gmail.com", it means a user will be created using this particular email address. If you try to sign in with any other provider or with an email and password using the same email address, you'll get an error message that says that the user already exists. And it makes sense since you have already used that email for a user before.
There are two ways in which you can solve this problem. When you get such an error, you can check the provider used to create the account, and notify the user to use it. For example, if the user signs in with Google and tries to authenticate with email and password right after that, display a message to the user in which you should say that the user already exists, and should use the authentication provider which was selected to create the account in the first place, in this case, Google.
The second option would be to allow the user to have multiple accounts using the same email address with different authentication providers. This option can be enabled directly in the Firebase Console, in the Authentication section.
So it's up to you to decide which option works better for your project.
The simple Solution is to enable multiple account an email.
Or ----------------
You Link the account.
This is an example when there is a facebook account with a certain email
and you want to use that same email to sign in with Email and password or gmail, if those two emails are not linked different provider error will be thrown. check here for more
export function linkFaceBookAccount(authContext?: AuthContextType, notificationContext?: NotificationContextType, history?: History.History) {
const provider = new FacebookAuthProvider(); // create a provider
linkWithPopup(auth.currentUser as User, provider).then((result) => {
// This gives you a Google Access Token. You can use it to access the Google API.
// const credential = FacebookAuthProvider.credentialFromResult(result);
// const token = credential?.accessToken;
// The signed-in user info.
const user = result.user;
saveUserToLocalStorage(user);
authContext?.loadUserToState(user);
notificationContext?.addNotification({
message: `This email's (${auth.currentUser?.email}) account has been successful linked with your facebook account`,
title: "Link successful",
notificationType: "SUCCESS",
positiveActionText: "continue",
positiveAction: () => {
history?.push("/")
}
})
}).catch((error) => {
const email = error.customData?.email;
const errorCode = error.code;
const duplicateAccount = errorCode === "auth/account-exists-with-different-credential";
notificationContext?.addNotification({
message: errorFirebase(error, email),
title: "Linking Error",
notificationType: "WARNING",
positiveActionText: duplicateAccount ? "Link" : "ok",
negativeActionText: duplicateAccount ? "cancel" : undefined,
code: errorCode,
positiveAction: () => {
if (duplicateAccount) {
duplicateAccountLinking(email, "FACEBOOK", history);
}
}
})
});}

Do Callable Cloud Functions Ensure a Valid Token when Called

I am calling a callable cloud function from a Javascript frontend and when calling Firebase in the past I would chain firebase.auth().currentUser.getIdToken(... before my call to the backend to ensure I had a valid token. Now that I am switching to callable cloud functions, I am wondering if this token refresh check is embedded in the callable itself or if I have to still check that my token is valid.
When calling a method returned by the callable builder, like const myFunc = httpsCallable(funcName); myFunc(/* data */);, only the current ID token is attached. If the token has not yet expired, it is not forcibly refreshed.
At least for the JavaScript SDK, this is seen in the source code of packages/functions/src/service.ts and packages/functions/src/context.ts:
// in packages/functions/src/service.ts
const context = await functionsInstance.contextProvider.getContext();
if (context.authToken) {
headers['Authorization'] = 'Bearer ' + context.authToken;
}
// in packages/functions/src/context.ts
async getAuthToken(): Promise<string | undefined> {
if (!this.auth) {
return undefined;
}
try {
const token = await this.auth.getToken();
return token?.accessToken;
} catch (e) {
// If there's any error when trying to get the auth token, leave it off.
return undefined;
}
}
This essentially leads to the following decisions:
If Firebase Authentication isn't loaded, return undefined (don't attach any tokens).
If the no one is logged in, return null (don't attach any tokens).
If the token has expired, attempt to get a fresh one (and then attach it to the request).
If the token can't be obtained, return undefined (don't attach any tokens).
If the token has not expired, return the access token (and then attach it to the request).
Even though token expiry is handled by the SDK, you can still forcibly freshen up the token by using getIdToken(/* forciblyRefresh: */ true) before calling the function. The Cloud Functions SDK will call the Admin SDK to verify whatever token is sent as soon as the request is received regardless.
Aside from that, you can further enhance the security of your Cloud Function by enforcing a cutoff on how long ago the user signed into their account for privileged actions like account deletion, changing service account details and so on. This is done using the auth_time claim inside the access token's data or the authTime property on the id token object.

Cannot pass a read permission (email) to a request for publish authorization

I am trying to use Facebook login using Firebase authentication. I have followed whole documentation. Lastly whenever I click the login button it gives an error saying:
Cannot pass a read permission (email) to a request for publish authorization
The line on which it is showing error is:
LoginManager.getInstance().logInWithPublishPermissions(LoginActivity.this,Arrays.asList("email", "public_profile"));
Can someone explain me what I am doing wrong? I have looked other answers also but no help from there.
Use logInWithReadPermissions instead of logInWithPublishPermissions. The error message is very clear about that, you are trying to request read permissions with a function that is being used for publish permissions.
.getInstance().logInWithPublishPermissions is not Firebase Authentication. Signin via federated providers such as Facebook is available via the Firebase JavaScript (web) SDK. See Authenticate Using Facebook Login with JavaScript for details.
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Facebook Access Token. You can use it to access the Facebook API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});

Error:"invalid_grant", Description:"Invalid JWT: Token must be a short-lived token and in a reasonable timeframe", Uri:""

I am trying to access google-calendar with the help of google service account
but i got belloing error
An exception of type 'Google.Apis.Auth.OAuth2.Responses.TokenResponseException' occurred in Google.Apis.dll but was not handled in user code
The error I am getting: "invalid_grant", Description:"Invalid JWT: Token must be a short-lived token and in a reasonable timeframe", Uri:""
string credPath = "key path";
String serviceAccountEmail = xxxx#developer.gserviceaccount.com";
var certificate = new X509Certificate2(credPath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { CalendarService.Scope.CalendarReadonly,
CalendarService.Scope.Calendar}
}.FromCertificate(certificate));
// Create the service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "HRTool",
});
var events = service.Events.List("my calaender id").Execute();
Invalid grant
When you try to use a refresh token, the following returns you an invalid_grant error:
Your server's clock is not in sync with network time protocol - NTP.
The refresh token limit has been exceeded.
First, kindly check the synchronization problem with the server clock, see the poor synchronization of the computer's clock answer for additional information. Second, check handling of refresh token and the old tokens. Some flows include additional steps, such as using refresh tokens to acquire new access tokens. For detailed information about flows for various types of applications, see Google's OAuth 2.0 documentation.
Hope this helps!
If you are getting the error of "Invalid JWT Signature." and if you are using the P12 certificate then confirm the P12 is correct or not for the Client Key you have used.
If you are getting the error of "Invalid JWT Signature." This is the error caused by some other plugin which you just installed check. I solved by removing rank math plugin as after this plugin install the elementor update was not working.

google analytics custom plugin getting error invalid grant

$client = new Google_Client();
$client->setAuthConfigFile(plugin_dir_url( __FILE__ ) . '/client_secrets.json');
$client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
$client->setIncludeGrantedScopes(true);
$client->setAccessType('offline');
$client->revokeToken();
$auth_url = $client->createAuthUrl();
using a popup authentication with javascript and then
if (!isset($_SESSION['access_token'])) {
//$client->authenticate($_GET['code']);
if($client->isAccessTokenExpired()){
$client->authenticate($this->options['authenication_code']);
$refreshToken = $client->getRefreshToken();
$client->refreshToken( $refreshToken );
$accessToken = $client->getAccessToken();
}
$_SESSION['access_token'] = $accessToken ? $accessToken : $refreshToken;
}
After authenticating It is giving the result ,but while using another session to get the data it is showing errors different error in different circumstances no clear idea
Google_Auth_Exception' with message 'Error fetching OAuth2 access
token, message: 'invalid_grant: Invalid code.'
Google_Auth_Exception' with message 'Error fetching OAuth2 access
token, message: 'invalid_grant' if checked after some time
Google_Auth_Exception' with message 'Error fetching OAuth2 access
token, message: 'invalid_grant: Code was already redeemed.' authenticated closed the browser and try with another browser
This is my 4th week on this but still unable to get things correctly.
I have gone through certain posts but no luck
1.Unable to refresh OAuth2 token in PHP, invalid grant
2.authenticate() accepts invalid tokens
3.Getting "invalid_grant" error on token refresh
4.Problem in refreshing access token
5.Why do I keep catching a Google_Auth_Exception for invalid_grant?
6.How to refresh token with Google API client?
7.Google OAuth2 - access token & refresh token -> invalid_grant/Code was already redeemed
8.Use OAuth Refresh Token to Obtain New Access Token - Google API
9.Using refresh_token for Google OAuth 2.0 returns http 400 bad request
and some more if I need to post more codes or anything else please let me know.
full code

Resources