Get Google refresh token when using Firebase Authentication - firebase-authentication

I am developing an Android app that has a Google Sign-in, provided by Firebase Authentication. I succeeded in getting an access token but this one expires and I need to prompt the user to re-sign-in. How can I get a refresh token? I searched all over StackOverflow but I have not found a solution that works for me.
This is how I get the access token:
val repoScope = CoroutineScope(Job() + Dispatchers.IO)
val token = repoScope.async {
GoogleAuthUtil.getToken(
context,
account,
"oauth2:https://www.googleapis.com/auth/calendar"
)
}
token.await()
I tried to get a refresh token making requests to the Google Oauth server but I always get 401 as a response
val client = OkHttpClient()
val requestBody: RequestBody? = FormEncodingBuilder()
.add("grant_type", "authorization_code")
.add("client_id", CLIENT_ID)
.add("client_secret", CLIENT_SECRET)
.add("code", acct.serverAuthCode)
.add("id_token", acct.idToken)
.build()
val request: Request = Request.Builder()
.url("https://www.googleapis.com/oauth2/v4/token")
.post(requestBody)
.build()

Related

Microsoft Graph access token refresh

I am writing an application that uses the "OAuth 2.0 client credentials grant flow" to get an access token for calling the Microsoft Graph API. The application authenticates as itself, not on behalf of a signed in user.
I based my code off of this example from Microsoft.
This is how I initialize the GraphServiceClient:
// Read application settings from appsettings.json (tenant ID, app ID, client secret, etc.)
AppSettings config = AppSettingsFile.ReadFromJsonFile();
// Initialize the client credential auth provider
var scopes = new[] { "https://graph.microsoft.com/.default" };
var clientSecretCredential = new ClientSecretCredential(config.TenantId, config.AppId, config.ClientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
And this is how I later use it (for example):
var users = await graphClient.Users.Request().GetAsync();
My application is an API. It is not an application that runs once and done. It will be continuously running for a long time. So I am concerned about what will happen when the access token expires. How do I make sure that when I need to use the graphClient the access token will not be expired?
According to your code snippet above, I think you are using the graph SDK and using the client credential flow as the authentication.
So we are no need to generate access token here but just using the graphClient to call the graph api and gather the information you needed. And due to this mode, it won't appear the token expired situation as each time you call an api you will new clientSecretCredential before it.
And let's come back to the refresh, azure ad provide refresh token for refreshing the access token when it expired as refresh token has much longer expire time than access token, when we try to get the refresh token, we need to append offline_access to the scope when generate the access. But using client credential flow means your app requests a new token with it's own credentials, so it's no need to using refresh token to avoid making signed-in user sign in again. Using credential flow shouldn't return refresh token.
Then you may have some ideas that you insist on using refresh the expired token process, then what you only can do is generate an access token first and save the token with its expired time in some place, and using the access token as the http request header and calling graph api. Then the code should like this, but I don't think you're willing to using this kind of code, you may also refer to this document for more details:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "your_azuread_clientid";
var clientSecret = "corresponding_client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(scopes);
var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
//using http sender with the token
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token );
// Call the web API.
HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
...
}

Get user profile details from Google using access token

We have mobile app developed in react native in which we have to implement Google and Facebook login. We have RN libraries using which we will get Facebook and Google user's profile details. But our requirement is like we need to just pass the access token to web api which is developed in asp.net core, and using the access token we have to verify the access token in asp.net core web api and fetch the user's profile details using Facebook or Google Apis.
It is working fine for Facebook api, below is the code for the same
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
Similarly, when we pass access token(id_token) for google, it is not working, and below is code for the same,
var token ="eyJhb.eyJpc....";
var httpClient1 = new HttpClient { BaseAddress = new Uri("https://www.googleapis.com/oauth2/v3/") };
var response1 = await httpClient1.GetAsync($"userinfo?access_token={token}");
Can anyone please assist me, how can we verify the access token and fetch the user's profile details?
Thanks In Advance.
You can verify your "id_token" and get some user profile details at the same time by making GET request to the next endpoint:
"https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123".
var token ="eyJhb.eyJpc....";
var httpClient1 = new HttpClient { BaseAddress = new Uri("https://oauth2.googleapis.com/") };
var response1 = await httpClient1.GetAsync($"tokeninfo?id_token={token}");
as described in google documentation "https://developers.google.com/identity/sign-in/web/backend-auth" (Calling the tokeninfo endpoint) section.
However in case you want to access google api services:
"id_token" is not meant to be used to access google api services, then you will need to have an "access_token" not an "id_token", you can follow the next documentation for that :
"https://developers.google.com/identity/protocols/oauth2"

No Session handle to Renew Token in Xero-Partner-App

Error from Xero :
Token does not match an expected REQUEST token
The issue seems to be related to the comment from the Xero help site?
This error will also occur if the session handle is not used in the
access token renewal process.
I have confirmed I do not get this on the return object of the following :
public async Task<AccessTokenDto> Authorise(string oauth_token, string oauth_verifier, string org)
{
var xeroacessToken =
_authenticator.RetrieveAndStoreAccessToken(_user.Name,
oauth_token, oauth_verifier, org);
}
I am not sure how I get the session handle and then how to use this in my service call to renew the token? As per the example I was expecting this on my token.
oauth_session_handle=ODJHMGEZNGVKMGM1NDA1NZG3ZWIWNJ
"Session Handle used to renew the access token"
Code that works the first time with the token that has been retrieved from the database:
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
var api = new RA.Xero.Partner.Core(tokenStore, XeroUser(UserId)), _hostingEnvironment)
{
UserAgent = "My Partner App " + input.ConsumerKey,
};
I tried to see if using the Partner Authentication directly would work :
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
Settings ApplicationSettings = new Settings();
X509Certificate2 certificate = RA.Xero.Partner.Core.Certificate(_hostingEnvironment);
var partnerAuthentication = new RA.Xero.Public.PartnerAuthenticator(
ApplicationSettings.Uri,
ApplicationSettings.AuthorizeUri,
ApplicationSettings.CallBackUri,
tokenStore,
certificate
);
var consumer = new Consumer(ApplicationSettings.Key,
ApplicationSettings.Secret);
var token = partnerAuthentication.GetToken(consumer,
XeroUser(UserId));
I have checked the keys are the partner keys in my app and any hints or sample code would be great.

Using JWT with Ktor and including user info in claim

I've successfully included a jwt auth token in my application and able to restrict access to the endpoints. I want to embed the user's ID in the jwt token, but I'm struggling how to implement the jwt verifier in Ktor.
I create a token for the client something like this:
val token = JWT.create().withAudience(audience).withIssuer(issuer).withClaim("userId", "XXX").sign(algorithm)
The route is setup like this. The authentication {} block is run on server startup and does not allow creating a verifier with the userId.
This was derived from the jwt sample:
route("/api") {
authentication {
val jwtVerifier = makeJwtVerifier(issuer, audience)
jwtAuthentication(jwtVerifier, realm) { credential ->
if (credential.payload.audience.contains(audience))
JWTPrincipal(credential.payload)
else
null
}
handle {
// Handle jwt succcess here
}
}
private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = JWT
.require(algorithm)
.withAudience(audience)
.withIssuer(issuer)
.build()
What is the correct way to do this? I understand I'd need to create a verifier for each request, but don't really know where to do this nor if that is desirable.
You should implement it in here. You don't need a verifier that checks user ids.
jwtAuthentication(jwtVerifier, realm) { credential ->
if (credential.payload.audience.contains(audience))
val userId = credential.payload.claims["userId"].asString()
// check if user exists ... if you want
JWTPrincipal(credential.payload)
else
null
}

Obtaining refresh_token through authentication api Auth0

How to obtain refresh_token along with the access_token while reissuing the access_token through authentication api of auth0 using resource owner flow?
I have tried with the below code
DelegationRequestBase delegationRequest = new RefreshTokenDelegationRequest(["auth0:ClientId"], ["auth0:ClientId"],refreshToken);
delegationRequest.Scope = "openid offline_access";
delegationRequest.GrantType = "refresh_token";
var res = cl.GetDelegationTokenAsync(delegationRequest).GetAwaiter().GetResult();
But I am getting below exception
Auth0.Core.Exceptions.ApiException
with message refresh_token is not supported
Is there any other interface or method to implement the same?