Firebase VerifyIdToken in Java Spring backend - java

I've a mobile application that using Google sign and trying to verify the token in backend (java spring).
I've set a few code for that, following many article.
FirebaseServiceCredential.java
This is for firebase connection, because i'm verifying using Admin SDK
package com.nostratech.nostrafood.config;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.database.FirebaseDatabase;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import java.io.FileInputStream;
import java.io.IOException;
#Slf4j
#Configuration
public class FirebaseServiceCredential {
public void firebaseConnect() throws IOException {
try {
FileInputStream serviceAccount = new FileInputStream("resources/charity-firebase-adminsdk-ymwjh-61467z75ba.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://charity.firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
FirebaseDatabase.getInstance(FirebaseApp.getInstance()).setPersistenceEnabled(true);
} catch (Exception e) {
log.debug("Trying to login to firebase failed. Reason: " + e.getMessage());
}
}
}
GoogleSignInService.java
This is code for verifyIdToken
package com.nostratech.nostrafood.service.base;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthException;
import com.google.firebase.auth.FirebaseToken;
import org.springframework.stereotype.Service;
#Service
public class GoogleSignInService {
public void verifyToken(String idToken) throws FirebaseAuthException {
FirebaseToken decodedToken =
FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
}
}
What should I do next for verify the token? I've read many article but still stuck dont know what to do.

If verifyIdToken() returns without throwing an exception, then the token is verified. No other action is needed to verify an ID token. The return value (FirebaseToken) gives you access to the UID and the JWT claims associated with the authenticated user.

Related

getValue not working on SAMLUserDetailsServiceImpl

I'm trying to implement SAML SSO on my project but there's a weird problem, the method getValue() is not working, it just says "Cannot resolve method 'getValue()'". Right on credential.getNameID().getValue() the getValue gets red and it shows that message, I've searched everywhere but found no answer
`
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.saml.SAMLCredential;
import org.springframework.security.saml.userdetails.SAMLUserDetailsService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
#Service
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {
// Logger
private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);
public Object loadUserBySAML(SAMLCredential credential)
throws UsernameNotFoundException {
// The method is supposed to identify local account of user referenced by
// data in the SAML assertion and return UserDetails object describing the user.
//PROBLEM RIGHT HERE
String userID = credential.getNameID().getValue();
LOG.info(userID + " is logged in");
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
authorities.add(authority);
// In a real scenario, this implementation has to locate user in a arbitrary
// dataStore based on information present in the SAMLCredential and
// returns such a date in a form of application specific UserDetails object.
return new User(userID, "<abc123>", true, true, true, true, authorities);
}
}
`
There's no much to try

Why is withRegion() of AmazonSNSClientBuilder not visible?

I am writing code to create an Amazon Web Services SNS client in Eclipse, when I get an error saying
The method withRegion(Region) from the type
AwsClientBuilder is not visible
Here is my code
package com.amazonaws.samples;
import java.util.Date;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.AnonymousAWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.sns.AmazonSNS;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.amazonaws.services.sns.model.PublishRequest;
// Example SNS Sender
public class Main {
// AWS credentials -- replace with your credentials
static String ACCESS_KEY = "<Your AWS Access Key>";
static String SECRET_KEY = "<Your AWS Secret Key>";
// Sender loop
public static void main(String... args) throws Exception {
// Create a client
AWSCredentials awsCred = new AnonymousAWSCredentials();
AWSStaticCredentialsProvider cred = new AWSStaticCredentialsProvider(awsCred);
Region region = Region.getRegion(Regions.US_EAST_1);
AmazonSNS service = AmazonSNSClientBuilder.standard().withRegion(region).withCredentials(cred).build(); // Error message: The method withRegion(Region) from the type AwsClientBuilder<AmazonSNSClientBuilder,AmazonSNS> is not visible
// Create a topic
CreateTopicRequest createReq = new CreateTopicRequest()
.withName("MyTopic3");
CreateTopicResult createRes = service.createTopic(createReq);
for (;;) {
// Publish to a topic
PublishRequest publishReq = new PublishRequest()
.withTopicArn(createRes.getTopicArn())
.withMessage("Example notification sent at " + new Date());
service.publish(publishReq);
Thread.sleep(1000);
}
}
}
In the screenshot it shows where the error occurs with the red underline in dotted line:
What should I check to correct this?
You are passing the wrong parameter, withRegion takes either a String or a Regions (note, not Region, singular).
Try passing Regions.EU_WEST_1.
Both AmazonSNSClientBuilder.standard().withRegion(Regions.EU_WEST_1).build();
and AmazonSNSClientBuilder.standard().withRegion("eu-west-1").build();
are working fine for me.

Firebase Upload in Java Spring Boot

I'm trying upload a file to Firebase storage in Java Spring Boot. I have looked on Stack Overflow and elsewhere online but have not found a working solution yet. Please help and thanks in advance!
So far I have the following code below, which is based on the code of this question:
// Input Firebase credentials:
FileInputStream serviceAccount = new FileInputStream("{{path to the keys}}");
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("{{url}}")
.build();
FirebaseApp.initializeApp(options);
// Other Firebase variables:
FirebaseApp storage = FirebaseApp.getInstance();
// Upload to Firebase:
BlobId blobId = BlobId.of("bucket", "blob_name");
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("text/plain").build();
Blob blob = storage.create(blobInfo, "Hello, Cloud Storage!".getBytes(UTF_8));
However, I cannot run this, as I get the following error:
UTF_8 cannot be resolved to a variable
If I remove the UTF_8 part, I get the following error:
The method create(BlobInfo, byte[]) is undefined for the type Object
You can try this:
Create a class to expose it as a web service in your API:
import com.yourcompany.yourproject.services.FirebaseFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
#RestController
public class ResourceController {
#Autowired
private FirebaseFileService firebaseFileService;
#PostMapping("/api/v1/test")
public ResponseEntity create(#RequestParam(name = "file") MultipartFile file) {
try {
String fileName = firebaseFileService.saveTest(file);
// do whatever you want with that
} catch (Exception e) {
// throw internal error;
}
return ResponseEntity.ok().build();
}
}
Create a service to upload the image to firebase storage.
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.Storage;
import com.google.firebase.cloud.StorageClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
import com.google.cloud.storage.StorageOptions;
import java.util.HashMap;
import java.util.Map;
#Service
public class FirebaseFileService {
private Storage storage;
#EventListener
public void init(ApplicationReadyEvent event) {
try {
ClassPathResource serviceAccount = new ClassPathResource("firebase.json");
storage = StorageOptions.newBuilder().
setCredentials(GoogleCredentials.fromStream(serviceAccount.getInputStream())).
setProjectId("YOUR_PROJECT_ID").build().getService();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public String saveTest(MultipartFile file) throws IOException{
String imageName = generateFileName(file.getOriginalFilename());
Map<String, String> map = new HashMap<>();
map.put("firebaseStorageDownloadTokens", imageName);
BlobId blobId = BlobId.of("YOUR_BUCKET_NAME", imageName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId)
.setMetadata(map)
.setContentType(file.getContentType())
.build();
storage.create(blobInfo, file.getInputStream());
return imageName;
}
private String generateFileName(String originalFileName) {
return UUID.randomUUID().toString() + "." + getExtension(originalFileName);
}
private String getExtension(String originalFileName) {
return StringUtils.getFilenameExtension(originalFileName);
}
}
Note you need to download Firebase config file and store it as "firebase.json" under the src/main/resources folder.
https://support.google.com/firebase/answer/7015592?hl=en
Also you need to add the Maven dependency:
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>6.14.0</version>
</dependency>

Facebook4j authentication issue

I am trying to make a java app which makes connection with facebook.I am using facebok4j to achieve this,I made an app in fb devolopers and got the key annd id for it.But when i am passing it to get an access token its returning an exception error.Please help me
java code
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import facebook4j.Facebook;
import facebook4j.FacebookException;
import facebook4j.FacebookFactory;
import facebook4j.Post;
import facebook4j.ResponseList;
import facebook4j.auth.AccessToken;
import facebook4j.auth.OAuthAuthorization;
import facebook4j.auth.OAuthSupport;
import facebook4j.conf.Configuration;
import facebook4j.conf.ConfigurationBuilder;
public class Fbsample {
public static Configuration createConfiguration()
{
ConfigurationBuilder confBuilder = new ConfigurationBuilder();
confBuilder.setDebugEnabled(true);
confBuilder.setOAuthAppId("*****");
confBuilder.setOAuthAppSecret("*****");
confBuilder.setUseSSL(true);
confBuilder.setJSONStoreEnabled(true);
Configuration configuration = confBuilder.build();
return configuration;
}
public static void main(String[] argv) throws FacebookException {
Configuration configuration = createConfiguration();
FacebookFactory facebookFactory = new FacebookFactory(configuration );
Facebook facebookClient = facebookFactory.getInstance();
AccessToken accessToken = null;
try{
OAuthSupport oAuthSupport = new OAuthAuthorization(configuration );
accessToken = oAuthSupport.getOAuthAppAccessToken();
}catch (FacebookException e) {
System.err.println("Error while creating access token " + e.getLocalizedMessage());
}
facebookClient.setOAuthAccessToken(accessToken);
//results in an error says {An active access token must be used to query information about the current user}
}
}
For now i specified my token and id as *.When running its returning 'Error while creating access token graph.facebook.com'.Thanks in advance.

Java EE FirebaseApp name [DEFAULT] already exists

I got a problem related to Firebase and Java EE.
I'm currently writing some Java servlets for my project and I'm using Firebase the first time because I wanted to try something new.
My actual problem is the following:
I got a servlet which is responsible for exchanging an iOS device token in an user database. This is necessary for sending Remote Push Notifications to a device.
I've done this like in the google tutorials, but I'm getting the following exception:
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
The way I'm accessing the Firebase Database is through the Java SDK.
I do this with the following code:
connect method
// gets called by the servlet to configure Firebase
public static void connect() {
try {
// for authentication purpose
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-account");
// Setting up the FirebaseOptions object
// constant FIREBASE_DATABASE_URL = "url to my database"
// constant FIREBASE_KEY_PATH = "path to my json key"
options = new FirebaseOptions.Builder()
.setDatabaseUrl(FIREBASE_DATABASE_URL)
.setServiceAccount(new FileInputStream(FIREBASE_KEY_PATH))
.setDatabaseAuthVariableOverride(auth)
.build();
FirebaseApp.initializeApp(options);
// calling the method for exchanging the token
exchangeIosDeviceToken("testmail#example.com", "5bf53173c9ef0a37638f3ddaa59cf2c0687c14ca0dcd47ccf57f9f09bd6368ab");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
exchangeIosDeviceToken method
public static boolean exchangeIosDeviceToken(String email, String newDeviceToken) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
// getting a reference to my "employee" child
DatabaseReference employeeReference = database.getReference("/employee");
Map<String, Object> employeeUpdates = new HashMap<>();
// updating the device token with child "iosDeviceToken" of "employee"
employeeUpdates.put(email+"/iosDeviceToken", newDeviceToken);
// update the actual children
employeeReference.updateChildren(employeeUpdates);
return true;
}
The funny part is when I'm trying to execute this code in a standalone main class (replacing the connect method, with the main method), the code is working.
Before you're saying things like "there are tons of questions related to this topic"... They are nearly all related to Android and questions related to my problem seldom got answered.
Regards
Solved the problem.
The problem was:
I've called the connect method everytime a request was incoming.
Solution:
Call the connect method only once. (ServletContextListener)
this for the future users, You can check whether the default app is initialized or not like this.
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if(firebaseApps!=null && !firebaseApps.isEmpty()){
for(FirebaseApp app : firebaseApps){
if(app.getName().equals(FirebaseApp.DEFAULT_APP_NAME))
firebaseApp = app;
}
}
else
firebaseApp = FirebaseApp.initializeApp(options);
This exception appear because you are trying to create the [DEFAULT] FirebaseApp again, simply you can add a validation to check if it exist or not before the initialization, like this:
if(FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME) != null) {
return;
}
My fix to this issue was call FirebaseApp.getInstance().delete();
My solution
package com.zs.configuration;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOpt`enter code here`ions;
import com.google.firebase.auth.FirebaseAuth;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
#WebListener
public class MyAppServletContextListener
implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
//Run this before web application is started
#Override
public void contextInitialized(ServletContextEvent arg0) {
try {
FileInputStream serviceAccount = new FileInputStream(getClass().getClassLoader().getResource("zs.json").getFile());
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://zs.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
FirebaseAuth.getInstance(firebaseApp);
}catch (Exception exc){
System.out.println("Firebase exception "+exc);
}
System.out.println("ServletContextListener started");
}
}
In my Application class
#ServletComponentScan
#SpringBootApplication
public class ZSApplication {
public static void main(String[] args) {
SpringApplication.run(ZSApplication.class, args);
}
}
Summarising all the solutions, very good ones BTW, proposed here: Running code after Spring Boot starts please find below the spring-boot (2.6.3) implementations which works for me.
Beware: Substitute with your app and files names below.
Placing the firebase initialisation method ( FirebaseApp.initializeApp(options)) directly on the main method (as I found on this tutorial: https://www.youtube.com/watch?v=8jK9O0lwem0) it caused the error, just because, debugging I notice, for some reason the call of the method FirebaseApp.initializeApp(options); is done multiple times.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import lombok.extern.slf4j.Slf4j;
#Slf4j
#SpringBootApplication
public class YourAppNameApplication {
public static void main(String[] args) {
SpringApplication.run(YourAppNameApplication.class, args);
}
/**
* Initialize the firebase SDK to integrate with the firebase application. Used
* for check the clients UIDs authentications.
*
* #throws IOException in case the firebase configuration JSON file is not
* present on the path.
*/
#EventListener(ApplicationReadyEvent.class)
public void initFirebaseSDK() throws IOException {
ClassLoader classLoader = YourAppNameApplication.class.getClassLoader();
File file = new File(
Objects.requireNonNull(classLoader.getResource("your_file_firebase.json")).getFile());
FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());
#SuppressWarnings("deprecation")
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://your_firebase_app_name.firebaseio.com").build();
FirebaseApp.initializeApp(options);
if (!(FirebaseApp.getApps().isEmpty())
&& FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName() != null) {
log.info("Firebase SDK has been initialised with the app name: "
+ FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName());
} else {
log.error(
"Firebase SDK has NOT been initialised. This is a serious error. Please contact the administrator of the app.");
}
}
}

Categories

Resources