Skip to content

ProductivityTools-Learning/ProductivityTools.Example.FirebaseAuthentication

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FirebaseAuthentication

This example shows how to use Firebase Authentication in two scenarios:

  • React application requesting protected resource from backend written in Python using Google authentication
  • Windows application requesting protected resource from console application written in C#

Diagram below presents all compoonents of the solution.

  • React aplication - web application needs to open google login window to receive bearer (id_token) token, next react will be calling the Cloud run application to get the resource
  • Console application - needs to call firebase to generate custom_token, next use this custom token to get id_token and with this id_token request for the resource
  • Cloud run - python application needs to validate bearer token and return data to react or to windows app

Arch

CloudRunPythonBackend

We have folowing resources

Firebase configuration

I choosed only the google provider

After creating project we need to add apps. We add web app

Console provides us snipped which should be added to our application

Next we need to add to our application code responsible for opening google login page it is described here

import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";

const auth = getAuth(app);

const googleProvider = new GoogleAuthProvider();
const signInWithGoogle = async () => {
    try {
        debugger;
        const res = await signInWithPopup(auth, googleProvider);
        console.log(res);
    } catch (err) {
        console.error(err);
        alert(err.message);
    }
};

Service account

To validate token we need to create firebase app. To do it we need to reference service account key. We can create application without any parameters default_app=initialize_app() then application will look for the file path under environment variable GOOGLE_APPLICATION_CREDENTIALS. In our example I will load service account key from drive.

Download service account key:

Service account key

Token validation

Probably there is more 'pro' way of validating token, I did it quick and dirty: auth.verify_id_token() returns data if token is correct and throws exception if not.

class ProtectedDateResource(Resource):
    def get(selfs):
        id_token=request.headers.environ["HTTP_AUTHORIZATION"]
        id_token=id_token.replace("Bearer","")
        id_token=id_token.replace(" ","")
        decoded_token=auth.verify_id_token(id_token)
        today=datetime.now()
        tstr=today.strftime('%m/%d/%Y %H:%m:%S')
        return tstr,HTTPStatus.OK

Our service should work

Console app

Console app do not have an interface in which we could login, so we need to create a customtoken on the server side and return it to the consol app. Then console app will take this custom_token and ask server with it to obtain access_token

Token service in backend app

It is easy we are creating endpoint which will return us token

class TokenResource(Resource):
    def get(self):
        custom_token=auth.create_custom_token("password123");
        return Response(custom_token, mimetype="text/plain",direct_passthrough=True)

Console app

To call the service first we get custom token, next with this custom token we are calling for the access_token and then for the resource.

string custom_token = await CustomToken.GetCustomToken();
Console.WriteLine($"Custom token: {custom_token}");
string access_token = await AccessToken.GetAccesToken(custom_token);
Console.WriteLine($"Access token: {access_token}");
string result = await RestService.GetResource(access_token);
Console.WriteLine(result);
Console.ReadLine();

Access token is retrieved from googleapis. To get it we need to call for the given adddress with Web API Key in the query

public static async Task<string> GetAccesToken(string custom_token)
{
    var HttpClient = new HttpClient();
    Uri url = new Uri(@"https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=AIzaSyDgSHqUdtL0XQ1i95Y_fMKTHV48Yjo_ZWs");

    HttpClient.DefaultRequestHeaders.Accept.Clear();
    HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    object obj = new { token = custom_token, returnSecureToken = true };
    var dataAsString = JsonConvert.SerializeObject(obj);
    var content = new StringContent(dataAsString, Encoding.UTF8, "application/json");

    HttpResponseMessage response = await HttpClient.PostAsync(url, content);
    if (response.IsSuccessStatusCode)
    {
        var resultAsString = await response.Content.ReadAsStringAsync();
        AccessToken result = JsonConvert.DeserializeObject<AccessToken>(resultAsString);
        return result.idToken;
    }
    throw new Exception(response.ReasonPhrase);
}

Working application:

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published