Seize the day

POST : Backend study

Firebase functions에서 Json web token(JWT) 만들기

Type스크립트로 jwt를 만들기 

[JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG  의 실습을 deno로 해 본다. 
test_jwt.ts 

import {encode as base64url_encode} from "https://deno.land/std@0.103.0/encoding/base64url.ts"
import {assertEquals} from "https://deno.land/std@0.103.0/testing/asserts.ts"

function json2Uint8Array(json: any) : Uint8Array {
    return new TextEncoder().encode(JSON.stringify(json))
}

// encode header
const header = {
    "typ": "JWT",
    "alg": "HS256"
  };
  
const encodedHeader = base64url_encode(json2Uint8Array(header));
assertEquals(encodedHeader, "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9")


// encode payload
const payload = {
    "iss": "velopert.com",
    "exp": "1485270000000",
    "https://velopert.com/jwt_claims/is_admin": true,
    "userId": "11028373727102",
    "username": "velopert"
};

const encodedPaylod = base64url_encode(json2Uint8Array(payload));
assertEquals(encodedPaylod, "eyJpc3MiOiJ2ZWxvcGVydC5jb20iLCJleHAiOiIxNDg1MjcwMDAwMDAwIiwiaHR0cHM6Ly92ZWxvcGVydC5jb20vand0X2NsYWltcy9pc19hZG1pbiI6dHJ1ZSwidXNlcklkIjoiMTEwMjgzNzM3MjcxMDIiLCJ1c2VybmFtZSI6InZlbG9wZXJ0In0")


// encode signiture
import {hmac as createHmac} from "https://deno.land/x/crypto@v0.10.0/hmac.ts"
const private_secret: Uint8Array = new TextEncoder().encode("secret")
const value = new TextEncoder().encode(encodedHeader + "." + encodedPaylod)
const hmacValue = createHmac('sha256', private_secret, value)
const signature = base64url_encode(hmacValue)
assertEquals(signature, "WE5fMufM0NDSVGJ8cAolXGkyB5RmYwCto1pQwDIqo2w")

console.log("JWT token: " + encodedHeader+ "." + encodedPaylod + "." + signature)

 

Firebase 로그인에서 JWT를 만들기

그것을 api 서버에서 private_secret로 검증해서 유효한 API call인지 검증할 수 있을 것 같다. 검증은 nginx에서 할 수 있을 듯...  ( Examples (nginx.org) )

제일 좋은 것은.. Nginx에서 JWT 검증도 하고, exp 만료도 체크하고, 데이타를 까서 특정 값을 헤더로 넣어주는 것이다.  API 서버에서는 헤더에서 가져와서 바로 사용하면 된다.
https://mostafa-asg.github.io/post/nginx-authentication-with-jwt/  아마도 nginx 를 새로 빌드를 해야할 듯하다. 


https://firebase.google.com/docs/functions/callable?hl=ko#java  참고..

# 라이브러리 설치
$ npm install -g firebase-tools

# firebase 로그인
$ firebase login

# 프로젝트 생성
$ firebase init

# 프로젝트 배포
$ firebase depoly

base64url은 base64의 문자중 3개를 (+ / =) 다른 것으로 교체하는 간단한 (jwt.io 방문해서 스펙을 확인)

npm install base64url

 

Firebase functions에서 JWT를 생성하는 코드, exp를 24시간을 준다.  
Index.js

const functions = require("firebase-functions");
const base64url = require('base64url');
const crypto = require('crypto');

const PRIVATE_SECRET = "blabla";
const MAX_EXPIRE_SECONDS = 60 * 60 * 24;    //24 hours

function generate_hs256_jwt(claims) {
    var header = { typ: "JWT",  alg: "HS256" };   
    var s = [header, claims].map(JSON.stringify)
                            .map(v=>base64url(v))
                            .join('.');

    var h = crypto.createHmac('sha256', PRIVATE_SECRET);

    return s + '.' + base64url(h.update(s).digest())
}

exports.createJwtToken = functions.https.onCall((data, context) => {
    // Message text passed from the client.
    const text = data.text;
    // Checking attribute.
    if (!(typeof text === 'string') || text.length === 0) {
        // Throwing an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
            'one arguments "text" containing the message text to add.');
    }
    // Checking that the user is authenticated.
    if (!context.auth) {
        // Throwing an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
            'while authenticated.');
    }

    // Authentication / user information is automatically added to the request.
    const fuid = context.auth.uid;
    
    var expireSeconds = MAX_EXPIRE_SECONDS;
    const exp = Math.floor(Date.now()/1000) + expireSeconds;

    var claims = {
        "iss": "lt",
        "exp": exp,
        "fuid": fuid
    };    

    try {
        const token = generate_hs256_jwt(claims);
        return {
            code: 0,
            result: {
                "exp": exp,
                "token": token
            }
        };
    } catch(error) {
        console.log(error);
        return  {
            code: 500,
            message: "generate_hs256_jwt() failed"
        };
    }
});

 

배포

firebase deploy --only functions:createJwtToken

 

안드로이드에서 호출하기는  https://dajkim76.tistory.com/537 참고

top

posted at

2021. 8. 5. 01:52


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크