Verifying firebase custom token with public key doen't work - java

Server side, i'm creating a custom tokens using a third-party JWT library
I'm using the private key token from the service account JSON file to sign the JWT.
I want to verify the token with the public keys provided by firebase (that we also find in the account JSON file)
My question is that firebase is providing public certificate like these exemples. I'm having problems using them since the jwt.io is always displaying 'not Verified'.
NB: I'm using Java in the backend and i don't want to use firebase service account ID.

Related

Get ServiceAccountCredentials from ComputeEngineCredentials to do user impersonation

I'm deploying a Java API that does user impersonation via Domain-widge Delegation to access the calendar of a user. For this I have created a service account, done the delegation and given it the right permissions and access to the users calendar.
While developing locally I've been using a downloaded key for the service account in the JSON format, and pointed to it with the GOOGLE_APPLICATION_CREDENTIALS environment variable. In my code, I create the credentials like this using the Java client library:
#Bean
#Qualifier("userCredentials")
public GoogleCredentials impersonateCalendarOwner() throws IOException {
final List<String> scopes = Collections.singletonList(CalendarScopes.CALENDAR);
return ((ServiceAccountCredentials) GoogleCredentials.getApplicationDefault())
.toBuilder()
.setServiceAccountUser(GOOGLE_CALENDARS_OWNER)
.build()
.createScoped(scopes);
}
This works fine locally, but when running in Cloud Run I get:
nested exception is java.lang.ClassCastException:
class com.google.auth.oauth2.ComputeEngineCredentials cannot be cast to
class com.google.auth.oauth2.ServiceAccountCredentials
After many hours of debugging I think I finally understand how getApplicationDefault works. I think what happens locally is this:
getApplicationDefault looks first at the environment variable GOOGLE_APPLICATION_CREDENTIALS, and because it is set it reads the credentials from that file
Because the file is a service account key file it creates a ServiceAccountCredentials instance so the "cast" succeeds.
And in Cloud Run it happens like this:
getApplicationDefault looks first at the environment variable GOOGLE_APPLICATION_CREDENTIALS, but on Cloud Run it isn't set
So it falls back to the service account identity the revision is running as by fetching the credentials from the Metadata server and returns them as an instance of ComputeEngineCredentials (since the Metadata server doesn't hand out the keys of the service account).
It then tries to cast ComputeEngineCredentials to ServiceAccountCredentials which obviously doesn't work.
So now my questions remain:
How can I convert some ComputeEngineCredentials to ServiceAccountCredentials?
Is there some other way to get the credentials as an instance of ServiceAccountCredentials instead?
Is there some other way to do user impersonation that doesn't require an instance of ServiceAccountCredentials?
My current idea is to use the ComputeEngineCredentials I get, to fetch the service account JSON key file from Secret Manager at service start up and then pass that file to ServiceAccountCredentials.fromStream but it feels like an extra step since the ComputeEngineCredentials I would be using are already the credentials of the same service account I would be fetching the key for.
The credentials provided by the instance metadata (Metadata server) does not include the service account private key which is required to sign requests.
Therefore the service account impersonation code that you are trying to use will not work. You will need to use an actual service account JSON that contains the private key.
My recommendation is to setup the default service account with a role to access Secret Manager. Store a service account JSON key file as data in Secret Manager. On your program startup fetch the service account JSON content and proceed with your impersonation code.
You need to tell the Cloud Run service to run as your service account:
gcloud run deploy --image IMAGE_URL --service-account SERVICE_ACCOUNT

Persisting the refresh token of the Spring OAuth2RestTemplate

I have a mobile application that uses my Spring Boot backend for things like authentication and accessing data. A part of the Spring Boot application accesses data from a resource server using OAuth2. I stumbled across an oauth2 client library for Spring that does its magic and everything just works out of the box.
As I'm trying to figure out how this library does its work, I can't seem to find an answer to the way it handles refresh tokens. I'm aware that the oauth2client is bound to a session for each user but what happens when the session ends? Wouldn't the access and refresh tokens get lost?
I was looking for ways to persist the refresh token for each user in my database but I didn't find any support for that in the library. This leaves me wondering if I have to implement this myself or if there's even a need to do so.
Any advice is appreciated!
Basically OAuth2 architecture is used for 3rd-party authentication and authorization. In this mechanism the credentials remains secured and aren't passed on while everything works upon tokens! But you can use it to work implicitly for your own authentication too.
In your case first when you hit "/oauth/token"(default endpoint) along with the client-secret and client-Id and rest of the user credentials the algo checks for the user details in the DB and matches the secret and Id present in the header of the request. If everything goes fine it'll generate a bearer type - access and refresh token and will store these tokens in different collections in the database.This particular user is mapped to these tokens and can access /api's using them only.No user creds are required. You can use MongoTokenStore if you're using MongoDb for storing and accessing stored tokens.
Next you have to configure WebSecurity/AuthorizationServer/ResourceServer for checking endpoints and header tokens tokens, authentication and authorizaton of users and providing valid tokens access to the resource respectively.
Lastly when you have a valid access token and hit an api with a correct header request the server grants you permission to access the resource!
This is the basic functionality of the OAuth2.0.
Normally Access Tokens have a shorter lifetime while refresh tokens have comparitively larger lifetime. Once Access Token gets expired a new Access Token can be generated using the Refresh Tokens. If the Refresh Tokens gets expired then you have to hit the "/oauth/token" api again,complete the flow cycle and generate tokens again.After expiry when you hit an api with existing access token they are removed from the collection. This is the default architecture of this mechanism, rest you can make custom classes and modify its functionality according to your needs! This architecture is quite secure and is a good practise.
Screenshot Flow Diagram
Check this post from digitalocean.
Edits ----
Personally I used MongoDB where I made two collections -
AuthAccessTokens and AuthRefreshTokens namely where these two were
stored. Access Token object has an Id of associated RefreshToken
which helps to map these two together. Rest custom additional Info.
can also be added using TokenEnhancer. Therefore tokens will always
be present in the DB unless expired. And in layman's terms if you
are just focussing on Backend stuff you can always check for your
access tokens by hitting "/oauth/token" with correct user creds and
it will return the assigned token by fetching it from the DB, else
if you're developing full stack after generating the tokens on first
step just store them on client end either in browser's local storage
or app. And if you want to deliberately end the session like for
example in Logout just remove these tokens from their respective
collections.

Spring boot OAuth2 sample

I have a Spring-Boot application with MongoDB. I want to register the client using OAuth2.0 strategy and store client-id and client secret key in database. I am able to generate the access token by using some dummy client and secret key from the below url: http://websystique.com/spring-security/secure-spring-rest-api-using-oauth2/
I want to know how to generate the client id and secret key in my java code. Any help is appreciated.
Client ID and secret are generated by service providers to let the developers register their application and access their API's.
There are many ways of generating Client_id and Client secret.It depends on your choice.
Client_id is a public identifier for apps.It should be unique and not easily guessable . So you could use like a 32-character hex string , Guid , Guid + systemTime ,also you can hash it , encrypt it or anything else you want to make it unique identifier. (you would find java code easily for the same)
Client_secret is a secret known only to the application and the
authorization server.So you could use a cryptographically-secure library to generate a 256-bit value and converting it to a hexadecimal representation.
You should avoid using common UUID libraries.
Also you should not store the secret in plain text, instead only store an encrypted or hashed version, to help reduce the likelihood of the secret leaking.
Here are some examples of client ID from services that support Oauth:
Foursquare: ZYDPLLBWSK3MVQJSIYRF1OR2JXCY0X2C5UJ2QAR2MAAIT5Q
Github: 6779ef20e75817b79602
Google: 292085223830.apps.googleusercontent.com
Instagram: f2a1ed52710d4533bde25be6da03b6e3

Accessing Google Sheets API via Service Account Key

I am working on Google Sheets <-> Salesforce integration and developing it in Salesforce programming language - Apex on Force.com platform.
Currently I am attempting to connect to Google Sheets API. I am using Service Account Key, so Salesforce can pull the data from Google Sheets without the requirement for manual authorisation every time it sends out a query.
I am at the point where I set up the Service Account Key and I am successfully sending a request to it to obtain the access_code.
Then I am attempting to query the API, using the following class:
/****** API CALLOUT *******/
public static HttpResponse googleSheetsCallout (){
//the below line provides a string containing access token to google
string accessCode = getAccessToken();
//I found this endpoint structure online, this may be why my script
//isn't working. However, I am struggling to find the alternative.
string endpoint = 'https://sheets.googleapis.com/v4/spreadsheets/params=[SPREADSHEET ID GOES HERE]/values/[RANGE GOES HERE]?access_token=';
httpRequest req = new httpRequest();
req.setEndpoint(endpoint+accessCode);
req.setMethod('GET');
req.setTimeout(120000);
httpResponse res = new http().send(req);
System.debug ('res is ' +res);
return res;
}
When I run the function this is what the log returns:
|CALLOUT_RESPONSE|[71]|System.HttpResponse[Status=Forbidden, StatusCode=403]
|USER_DEBUG|[72]|DEBUG|res is System.HttpResponse[Status=Forbidden, StatusCode=403]
I enabled Google Sheets access in the google developer console menu, and what's interesting is when loking at the console it appears that Google notices API requests being sent out (they are appearing on the activity chart).
I solved it, and the issue was not the code itself.
The problem was sharing my sheet. To allow read/edit access to your sheet from the service account it must be shared with the Service Account ID email address, the same way it's shared with any other user. If this isn't done the script will produce 403 error.

Android OAuth with valid "CONSUMER_KEY" and "CONSUMER_SECRET"

I have a valid consumer_key and consumer_secret for my app to access resources on a certain website.
I create the consumer like this:
private void createConsumer(){
mConsumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
}
I create the provider like this:
private void createProvider(){
mProvider = new CommonsHttpOAuthProvider(REQUEST_TOKEN_URL, ACCESS_TOKEN_URL,
AUTHORIZE_URL);
}
I then use an AsyncTask to retrieve what I assume is a valid AccessToken from the server.
mAccessTokenUrl = mProvider.retrieveRequestToeken(mConsumer, CALL_BACK_URL);
with this call I get something similar to this:
``http://www.mygarden.org/oauth/authorize?/oauth_token=XXXXXXXXXXXXXXhs343sjd&oauth_callback=http%3A%2F%2Flocalhost
I'm assuming the token is correct because if I test this with the incorrect credentials I don't get anything back.
Question 1:
Is this callback url corrent, because on the site it does not specify a callback url, just the app's website; and how should I use it on the android app?
Question 2:
How do I now use the Access Token to consume certain services on the website, for example to get all the plants I should use this link: http://api.mygarden.org/activities/all which should return certain data in xml/json format
Extra information is that all calls to the API should use the http GET method unless specified otherwise. I do not want the user to first register on the site, I just want to consume the services they provide using my app's access credentials. If user credentials are necessary, could I embed them within the URL and grant the user access automatically?
The website is: http://www.mygarden.org
Thanks for your help.
To get a list of all the plants you don't need to authenticate a user. This is only necessary for user related actions, like posting status updates or adding plants to your garden.
So you only have to send a call to oauth/request_token and then oauth/access_token, after that you're ready to get some data from the API
Answer for Question 1:
If your developing an android application you don't need the callback url, this is needed when you want to authenticate a user trough a website. Make sure you select Client in the app settings on mygarden.org
Answer for Question 2:
To get all the plants you need plants/all. If you're using a standard oauth library, all the required oauth parameters are automatically added to your query
I'm a developer at mygarden.org, you can always contact our support ;)

Categories