재우니의 블로그

Firebase API 호출 Wrapper() 만들어 활용하기

 

www.ashishvishwakarma.com/creating-c-sharp-wrapper-over-firebase-api-for-basic-crud/

 

Creating C# Wrapper Over Firebase API For CRUD Operations

 

www.ashishvishwakarma.com

Firebase  API 호출 시, 구글 서비스를 통해 Access-token 적용해 보기

 

www.c-sharpcorner.com/article/retrieve-access-token-for-google-service-account-form-json-or-p12-key-in-c-sharp/

 

Generate Access Token For Google Service Account Form JSON Or P12 Key In C#

Service Accounts are used for server to server communication so users don't need to interact for Authentication. Let's learn to get access token for Google Service Account.

www.c-sharpcorner.com

 

Firebase 읽기 / 쓰기 액세스는 RULES 에서 볼 수 있듯이 기본적으로 보호됩니다 .

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

 

 

IAM 의 서비스 계정에서 키를 발급 받습니다.

 

console.cloud.google.com/projectselector2/iam-admin/serviceaccounts?supportedpurview=project

 

Google Cloud Platform

하나의 계정으로 모든 Google 서비스를 Google Cloud Platform을 사용하려면 로그인하세요.

accounts.google.com

프로젝트를 선택합니다.

 

키관리를 선택합니다.

 

 

키 추가를 통해서 키가 없었으면 새 키 만들기를 선택합니다. 선택 후 브라우저에서 json 형태로 파일을 받습니다.

1번 : 받은 json 내용물을 복사해서  key.json 파일을 열어서 본문에 붙여 넣습니다.

2번 : key.json 파일은 출력 디렉터리로 복사를 "항상 복사" 로 설정합니다.

3번 : program.cs 파일을 열어서 키 값 위치 인, json 파일 위치를 기재해 줍니다.

 

이제 실행하면, 이를 통해 access_token  값을 가져와서 firebase 의 데이터를 추가, 수정, 삭제, 조회까지 가능합니다.

 

using Google.Apis.Auth.OAuth2;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace FirebaseNet.Auth
{
    class AuthHelper
    {
        public static string ACCESS_TOKEN { get; set; }

        private static string jsonKeyFilePath;

        private static string[] scopes;

        private static async Task<string> GetAccessTokenFromJSONKeyAsync(string jsonKeyFilePath, params string[] scopes)
        {
            using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
            {
                return await GoogleCredential
                    .FromStream(stream) // Loads key file
                    .CreateScoped(scopes) // Gathers scopes requested
                    .UnderlyingCredential // Gets the credentials
                    .GetAccessTokenForRequestAsync(); // Gets the Access Token
            }
        }

        public static void GenenateAccessToken(string jsonKeyFilePath, params string[] scopes)
        {
            AuthHelper.jsonKeyFilePath = jsonKeyFilePath;

            if (scopes.Length == 0)
                AuthHelper.scopes = new string[] { "https://www.googleapis.com/auth/firebase", "https://www.googleapis.com/auth/userinfo.email" };
            else
                AuthHelper.scopes = scopes;

            ACCESS_TOKEN = GetAccessTokenFromJSONKeyAsync(jsonKeyFilePath, AuthHelper.scopes).Result;
        }

        public static void RefreshToken()
        {
            if (!string.IsNullOrEmpty(ACCESS_TOKEN))
                ACCESS_TOKEN = GetAccessTokenFromJSONKeyAsync(jsonKeyFilePath, scopes).Result;
            else
                throw new InvalidOperationException("Unauthorised! Generate a token first.");
        }
    }
}

 

RequestHelper() 를 보면 호출시 access_token 값을 전송하여 이를 검증받아 firebase 로 부터 데이터를 핸들링 가능합니다. 

//-----------------------------------------------------------------------
// <copyright file="UtilityHelper.cs" company="AshishVishwakarma.com">
// Github/AshV
// </copyright>
// <author>Ashish Vishwakarma</author>
//-----------------------------------------------------------------------
namespace FirebaseNet.Database
{
    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json.Linq;
    using FirebaseNet.Auth;

    /// <summary>
    /// Utility Helper Class
    /// </summary>
    class UtilityHelper
    {
        /// <summary>
        /// User Agent Header in HTTP Request
        /// </summary>
        private const string USER_AGENT = "firebase-net/0.2";

        /// <summary>
        /// Validates a URI
        /// </summary>
        /// <param name="url">URI as string</param>
        /// <returns>True if valid</returns>
        public static bool ValidateURI(string url)
        {
            Uri locurl;
            if (System.Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out locurl))
            {
                if (
                    !(locurl.IsAbsoluteUri &&
                      (locurl.Scheme == "http" || locurl.Scheme == "https")) ||
                    !locurl.IsAbsoluteUri)
                {
                    return false;
                }
            }
            else
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Validates JSON string
        /// </summary>
        /// <param name="inJSON">JSON to be validatedd</param>
        /// <param name="output">Valid JSON or Error Message</param>
        /// <returns>True if valid</returns>
        public static bool TryParseJSON(string inJSON, out string output)
        {
            try
            {
                JToken parsedJSON = JToken.Parse(inJSON);
                output = parsedJSON.ToString();
                return true;
            }
            catch (Exception ex)
            {
                output = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// Makes Asynchronus HTTP requests
        /// </summary>
        /// <param name="method">HTTP method</param>
        /// <param name="uri">URI of resource</param>
        /// <param name="json">JSON string</param>
        /// <returns>HTTP Responce as Task</returns>
        public static Task<HttpResponseMessage> RequestHelper(HttpMethod method, Uri uri, string json = null)
        {
            if (!string.IsNullOrEmpty(AuthHelper.ACCESS_TOKEN))
                uri = new Uri($"{uri}?access_token={AuthHelper.ACCESS_TOKEN}");

            var client = new HttpClient();
            var msg = new HttpRequestMessage(method, uri);
            msg.Headers.Add("user-agent", USER_AGENT);
            if (json != null)
            {
                msg.Content = new StringContent(
                    json,
                    UnicodeEncoding.UTF8,
                    "application/json");
            }

            return client.SendAsync(msg);
        }
    }
}

 

오류 발생시 refresh_token 으로 호출하여 다시 access-token 을 전송하여 처리합니다.

//-----------------------------------------------------------------------
// <copyright file="FirebaseRequest.cs" company="AshishVishwakarma.com">
// Github/AshV
// </copyright>
// <author>Ashish Vishwakarma</author>
//-----------------------------------------------------------------------
namespace FirebaseNet.Database
{
    using FirebaseNet.Auth;
    using System;
    using System.Net;
    using System.Net.Http;

    /// <summary>
    /// Firebase Request
    /// </summary>
    class FirebaseRequest
    {
        /// <summary>
        /// Suffix to be added in each resource URI
        /// </summary>
        private const string JSON_SUFFIX = ".json";

        /// <summary>
        /// Initializes a new instance of the <see cref="FirebaseRequest"/> class
        /// </summary>
        /// <param name="method">HTTP Method</param>
        /// <param name="uri">URI of resource</param>
        /// <param name="jsonString">JSON string</param>
        public FirebaseRequest(HttpMethod method, string uri, string jsonString = null)
        {
            this.Method = method;
            this.JSON = jsonString;
            if (uri.Replace("/", string.Empty).EndsWith("firebaseio.com"))
            {
                this.Uri = uri + '/' + JSON_SUFFIX;
            }
            else
            {
                this.Uri = uri + JSON_SUFFIX;
            }
        }

        /// <summary>
        /// Gets or sets HTTP Method
        /// </summary>
        private HttpMethod Method { get; set; }

        /// <summary>
        /// Gets or sets JSON string
        /// </summary>
        private string JSON { get; set; }

        /// <summary>
        /// Gets or sets URI
        /// </summary>
        private string Uri { get; set; }

        /// <summary>
        /// Executes a HTTP requests
        /// </summary>
        /// <returns>Firebase Response</returns>
        public FirebaseResponse Execute()
        {
            Uri requestURI;
            if (UtilityHelper.ValidateURI(this.Uri))
            {
                requestURI = new Uri(this.Uri);
            }
            else
            {
                return new FirebaseResponse(false, "Provided Firebase path is not a valid HTTP/S URL");
            }

            string json = null;
            if (this.JSON != null)
            {
                if (!UtilityHelper.TryParseJSON(this.JSON, out json))
                {
                    return new FirebaseResponse(false, string.Format("Invalid JSON : {0}", json));
                }
            }

            var response = UtilityHelper.RequestHelper(this.Method, requestURI, json);
            response.Wait();
            var result = response.Result;

            if (!result.IsSuccessStatusCode && result.StatusCode.Equals(HttpStatusCode.Unauthorized))
            {
                AuthHelper.RefreshToken();
                response = UtilityHelper.RequestHelper(this.Method, requestURI, json);
                response.Wait();
                result = response.Result;
            }

            var firebaseResponse = new FirebaseResponse()
            {
                HttpResponse = result,
                ErrorMessage = result.StatusCode.ToString() + " : " + result.ReasonPhrase,
                Success = response.Result.IsSuccessStatusCode
            };

            if (this.Method.Equals(HttpMethod.Get))
            {
                var content = result.Content.ReadAsStringAsync();
                content.Wait();
                firebaseResponse.JSONContent = content.Result;
            }

            return firebaseResponse;
        }
    }
}

 

 

Firebase.Net-master.zip
1.99MB