Initializing Firebase Admin in App Engine standard Golang - firebase

I'm on golang app engine standard. I keep getting a 403 error when I'm using a firebase. Here is the code I'm using for passing credentials for firebase. What is this api key? What am I doing wrong?
Error:
googleapi: Error 403: The request is missing a valid API key., forbidden
credJSON := []byte("{...json from firebase console...}")
creds, err := google.CredentialsFromJSON(ctx, credJSON, "https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/datastore",
"https://www.googleapis.com/auth/devstorage.full_control",
"https://www.googleapis.com/auth/firebase",
"https://www.googleapis.com/auth/identitytoolkit",
"https://www.googleapis.com/auth/userinfo.email")
if err != nil {
return err
}
ops = append(ops, option.WithCredentials(creds))
fbApp, err := fb.NewApp(ctx, &fb.Config{ProjectID: projectID}, ops...)

Turns out if you pass nil for config. The library figures out credentials on Google Cloud. So, here is the code:
fbApp, err := fb.NewApp(ctx, nil, ops...)
if err != nil {
return nil, err
}

Related

How to validate the firebase jwt token in my google cloud function?

Users are authenticated in the frontend via
const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(googleAuthProvider);
after that I am calling a cloud function with the firebase callable:
const nodeStateCall = functions.httpsCallable('myFunction');
nodeStateCall().then(...);
This workks without any problems and I recieve the jwt token in my go function.
I tried many different variations to authenticate this token. The function which I am using now is idtoken.Validate() from the google.golang.org/api/idtoken pacakge.
My function:
func verifyIdToken(idToken string)(tokenInfo *idtoken.Payload, err error) {
log.Print("running verify Token")
splitToken := strings.Split(idToken, "Bearer ")[1]
log.Print("split Token:"+splitToken)
tokenInfo, err = idtoken.Validate(context.Background(),splitToken,"MYAUDIENCE")
if err != nil {
log.Print("error from tokenInfoCall.Do()")
log.Print(err)
return nil, err
}
log.Print("Finished verify token.")
return tokenInfo, nil
}
but I keep getting "invalid value" when I send the token.
I also tried the oauth2 service:
oauth2Service, err := oauth2.NewService(context.Background())
tokenInfoCall := oauth2Service.Tokeninfo()
tokenInfoCall.IdToken(splitToken)
tokenInfo, err := tokenInfoCall.Do()
which didn't work either.
What do I have to do to validate the firebase jwt token in my go function?
Because you are using firebase service, you need to use this to verify your token:
https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_the_firebase_admin_sdk
Note that you should setup your function in the same project so the library will query correctly.

Golang Wasm HTTP Request Failing

I'm a little stuck on a Golang wasm request. The code works just fine in a service when I test it, but when I try to run it in a browser with wasm I get a fetch failed error. This code runs just fine if I call it from a stand-alone service:
go func() {
authURL := "https://auth.home.rsmachiner.com/login"
type loginStruct struct {
Username string `json:"username"`
Password string `json:"password"`
}
fmt.Println("Pushed login button")
fmt.Printf("Got Login: %v\n", r.LoginBoxValue)
fmt.Printf("Got Password: %v\n", r.PasswordValue)
var login loginStruct
login.Username = r.LoginBoxValue
login.Password = r.PasswordValue
data, err := json.Marshal(&login)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(data))
req, _ := http.NewRequest("POST", authURL, bytes.NewBuffer(data))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("response error")
fmt.Println(err)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Print("BODY:")
fmt.Println(string(body))
}()
Which throws the following error:
Post "https://auth.home.rsmachiner.com/login": net/http: fetch() failed: Failed to fetch
When I try it from a standalone client it works fine. The server is allowing CORS as well with
w.Header().Set("Access-Control-Allow-Origin", "*")
For anyone that stumbles on this, it works fine in a browser too. The problem was the HTML not the code. The HTML was making the page reload so the request was failing due to being terminated.

How to verify if Google Firebase admin SDK credentials are correct

Is there any way to verify if Firebase Admin SDK Credentials is correct when initializing app with below code?
ctx := context.Background()
opt := option.WithCredentialsFile("path/to/firebase-admin-sdk-cred.json")
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
return nil, err
}
Because I seem to not get any error when I tried to intentionally put the wrong credentials. I check the implementation of the firebase.NewApp() but it seems it only throw error when there is no config. Below is the code of firebase.NewApp()
func NewApp(ctx context.Context, config *Config, opts ...option.ClientOption) (*App, error) {
o := []option.ClientOption{option.WithScopes(internal.FirebaseScopes...)}
o = append(o, opts...)
if config == nil {
var err error
if config, err = getConfigDefaults(); err != nil {
return nil, err
}
}
pid := getProjectID(ctx, config, o...)
ao := defaultAuthOverrides
if config.AuthOverride != nil {
ao = *config.AuthOverride
}
return &App{
authOverride: ao,
dbURL: config.DatabaseURL,
projectID: pid,
serviceAccountID: config.ServiceAccountID,
storageBucket: config.StorageBucket,
opts: o,
}, nil
}
so Is there any way to check if the credentials is valid during the initialization of Firebase Admin(app) instance because it seems catching error isn't the solution here?
I think the answer is in the documentation:
Some use cases require you to create multiple apps at the same time.
For example, you might want to read data from the Realtime Database of
one Firebase project and mint custom tokens for another project. Or
you might want to authenticate two apps with separate credentials. The
Firebase SDK allows you create multiple apps at the same time, each
with their own configuration information.
Source
I assume the only way to check credentials is invoke an Auth method for example:
client, err := app.Auth(context.Background())
I ended up using google.golang.org/api/transport to force the validation and fail fast
// Check if credential is correct
_, err = transport.Creds(ctx, opt)
if err != nil {
return nil, err
}

Issuing HTTP Get Request in Flexible Environment in App Engine

I am using Flexible Environment in App engine I want to send HTTP Get request in my code.
ctx := appengine.NewContext(r)
client := urlfetch.Client(ctx)
req, err := http.NewRequest("GET", "https://www.google.com/", nil)
res, err := client.Do(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "HTTP GET returned status %v", res.Status)
When I run app I get the following error:
https://www.google.com/: not an App Engine context
The above code works in Standard Environment and but it is not working in flexible environment.
You don't need URL Fetch in App Engine Flexible, you can simply issue the http request: https://cloud.google.com/appengine/docs/flexible/go/migrating#url_fetch

FCM HTTP v1: how to get access token using Go?

In order to send Firebase Cloud Messaging with Go, we need to place the access token in the HTTP request header.
On Firebase documentation,
there are examples on how to retrieve the access token using Node.JS, Python and Java:
https://firebase.google.com/docs/cloud-messaging/auth-server
can anyone show the get the access token using Go?
There seems to be many Go packages about Firebase/Google authentication. It's very confusing to understand which ones should be used:
firebase.google.com/go
firebase.google.com/go/auth
github.com/firebase/firebase-admin-go
google.golang.org/api/option
golang.org/x/oauth2
golang.org/x/oauth2/google
github.com/google/google-api-go-client
I'm working on the go firebase SDK to add FCM HTTP v1.
For now it's almost finished, i have to write tests and integration tests, you can check the code here : https://github.com/chemidy/firebase-admin-go/tree/fcm/messaging
I will finish tests and send a PR maybe next week, (it's a little bit tricky to test on ios + android + web)
FCM httpv1 use JSON file for it credentials.
Download it first, then move it to your project.
download JSON credentials in your firebase
second, do :
go get "golang.org/x/oauth2/google"
then use this method to get token
const firebaseScope = "https://www.googleapis.com/auth/firebase.messaging"
type tokenProvider struct {
tokenSource oauth2.TokenSource
}
// newTokenProvider function to get token for fcm-send
func newTokenProvider(credentialsLocation string) (*tokenProvider, error) {
jsonKey, err := ioutil.ReadFile(credentialsLocation)
if err != nil {
return nil, errors.New("fcm: failed to read credentials file at: " + credentialsLocation)
}
cfg, err := google.JWTConfigFromJSON(jsonKey, firebaseScope)
if err != nil {
return nil, errors.New("fcm: failed to get JWT config for the firebase.messaging scope")
}
ts := cfg.TokenSource(context.Background())
return &tokenProvider{
tokenSource: ts,
}, nil
}
func (src *tokenProvider) token() (string, error) {
token, err := src.tokenSource.Token()
if err != nil {
return "", errors.New("fcm: failed to generate Bearer token")
}
return token.AccessToken, nil
}
Then call it in your FCM-Send method :
tp, err := newTokenProvider("yourJSONFileLocation")
if err != nil {
return nil, err
}
token, err := tp.token()
if err != nil {
return nil, err
}
last, add it to header :
r.Header.Add("Authorization", "Bearer "+token)
Done.
i am put header Authorization by used volly
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headerMap = new HashMap<String, String>();
headerMap.put("Content-Type", "application/json");
headerMap.put("Authorization", "Bearer " + key);
Log.v(TAG,"getHeaders "+headerMap);
return headerMap;
}
but send Authorization=Bearer Add..
how change to current
Authorization:Bearer

Resources