Skip to content

Commit

Permalink
Merge dc07f6f into a96e468
Browse files Browse the repository at this point in the history
  • Loading branch information
cookingkode committed Sep 9, 2016
2 parents a96e468 + dc07f6f commit ace23b7
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
90 changes: 90 additions & 0 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/SermoDigital/jose/crypto"
"github.com/SermoDigital/jose/jws"
"strings"
"time"
)
Expand All @@ -17,6 +20,8 @@ const (
TokenSep = "."
// MaxUIDLen is the maximum length for an UID
MaxUIDLen = 256

firebaseAudience = "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
)

// Firebase specific values for header
Expand Down Expand Up @@ -144,3 +149,88 @@ func sign(message, secret string) string {
h.Write([]byte(message))
return encode(h.Sum(nil))
}

func GenerateCustomToken(uid string, developerClaims *jws.Claims, clientEmail string, privateKeyString string) (string, error) {

privateKey, err := crypto.ParseRSAPrivateKeyFromPEM([]byte(privateKeyString))
if err != nil {
return "", err
}

if uid == "" {
return "", errors.New("Uid must be provided.")
}

if clientEmail == "" {
return "", errors.New("Must provide an issuer.")
}

method := crypto.SigningMethodRS256
claims := jws.Claims{}
claims.Set("uid", uid)
claims.SetIssuer(clientEmail)
claims.SetSubject(clientEmail)
claims.SetAudience(firebaseAudience)
now := time.Now()
claims.SetIssuedAt(now)
claims.SetExpiration(now.Add(time.Hour))

if developerClaims != nil {

for claim := range *developerClaims {
if isReserved(claim) {
return "", fmt.Errorf("developer_claims cannot contain a reserved key: %s", claim)
}
}
claims.Set("claims", developerClaims)
}

jwt := jws.NewJWT(claims, method)
bytes, err := jwt.Serialize(privateKey)
if err != nil {
return "", err
}

return string(bytes), nil
}

// isReserved determines whether a given name is a reserved name via binary search.

var (
reservedNames = []string{
"acr",
"amr",
"at_hash",
"aud",
"auth_time",
"azp",
"cnf",
"c_hash",
"exp",
"firebase",
"iat",
"iss",
"jti",
"nbf",
"nonce",
"sub",
}
)

func isReserved(name string) bool {
if len(reservedNames) > 0 {
l, r := 0, len(reservedNames)-1
for l <= r {
m := l + (r-l)/2
curr := reservedNames[m]
if curr == name {
return true
} else if curr > name {
r = m - 1
} else /* if curr < name */ {
l = m + 1
}
}
}
return false
}
49 changes: 49 additions & 0 deletions generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"github.com/SermoDigital/jose/jws"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -137,3 +138,51 @@ func TestSign(t *testing.T) {
t.Fatalf("expect:%v, but got:%v", g.out, got)
}
}

func TestCustomAuthTokenValid(t *testing.T) {
private_key := "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXJ2PtihileBbe\nmgc4tckfZNf4ZXHYevhOJs7zj9lBxD4+CBvw9WWFBhnIvLhq42DoxPFz8jYbWsh9\nj7dFp9y0TDUiIIsvTm/KNJ9mL2ttgFiOZEdS9k8N1I9dDkM2UNi7WtGP03Tm0Abz\nfrvSCJKro3lr8+tzCzfV0rtkhIaurbOy3f+iy1Bh2dQ+m6bkc4IKFHeqKPEp46mp\nagGgxergN0WIHfhcjFXkL+GspcuRw8C+AX84GZHmefyYycXY1R0DkSWMTm5q1MUs\ny5rbiCNtHW/elXoVbnlvSka3+GM9HRFXrevF+BmJHk1AziOBy49R5fgmw92/LwNQ\n3KzJl5rBAgMBAAECggEAWov0TRrKJpE0prgSA/bVTsYE8j/XOrD94P4KKIzIdRoe\ny8Jj5/OOpv4bSdTKlAlfVnbT2uT7imWZbOZXzhPIGYTc86DYkq8i8ulUkA+y2WGj\nY0Gmlq6cNIjZUONYu/ooTCj7etkWILE5y63xY4JCH8PrrNf5pe/5rp5CSRpRCB/C\nZI1Arjy7ZUPaGypAH58gakDDBWIiSCRsFX+0bt5u+J+FWebcurYQ+Y+qdpJ6cKbZ\nen0AWHQroxpWw7dWwsSriUYroKJMKLt5zM/wOJ5N4qKVwpuJX6qWB7C6JyyOZaJY\nEM5oOdMl94/Ml3gUpyfWRwV2qJkSFsvwd895hOkrhQKBgQD30WauA0SiVcHQowu/\ngbszKGaWwkoELFhPxUrtNZrQdQYBBoqft5nEA0mzY5DSoDgs4SDTMJ8HlA79XOKd\nlqCBeKWxS10zGOIxx+qWPpkulRnQek1088ZBGBxDu8V+SVfEqH+sQLEN4H9lYNe0\nRCTxrLVGcv2bezv3rpC2vKFmQwKBgQDeQegi6a73UUJV3yYGM8VBfmZjUCGb5KdH\nH8b1nc+Ty7C0z7nXU1zizN9ZZaIVMivfSt8H2W+3ikQ4FY8f7DAAQmw2JFrvKb4N\n/nnQXGIcRfO/RdM8ui88Oh7uJgZrkE9SbaWoVlhzZOv64aLqi/TZAN5UstIpNLfA\nS9s2bz/EqwKBgQCkQBELMrVR1v8PtpE5y9V0ccmVEI8YNwANVxlzIT1L/tQM5/YH\nKBxtMzStBkfdoj25WTl1YFt3HWXV/bNheY1GYt2HJglOraZ2EifkjvbeTgp/CCDA\nbDYxvLY3GoQqUJgwivGcDICNTweA/O/a1fOajrrTR7HZVJOJdRULWPismwKBgDs1\njZT3chAayrQ7rVKLqioHdVlRuJJiOJn/Ai7eqrTx15JjoFuXrrAQ6hNTuvkwk3V5\n6a6ao2Ne50uVmrpjXmpDR7aourzp/uKVf3gdlFl53TSAcoTECN9fkGvbH2y6Vhdc\ndHxC/G9JXIBKae9X95Nz4sbnmIs3qxgEXVLEElXfAoGAMgmwfSWOcdBahUvpiwOu\nJ0vJH5rmPYtBoFdd418Ynji2O0/8R9N5gDshff7ns6NBL/u1OS23fESWs4Lv09Hh\nS/ExVyxe2sa1RyDVbljLH5+aLkpWCfiNEFGcJ0kyIucPzjHJLCC6dTKh84fSTPRm\nWRRCbVUmvLnwcpIpPMhcnTc=\n-----END PRIVATE KEY-----\n"
client_email := "test@testing.iam.gserviceaccount.com"
userid := "tester"

if _, err := GenerateCustomToken(userid, nil, client_email, private_key); err != nil {
t.Fatal(err)
}
}

func TestCustomAuthTokenInValidKey(t *testing.T) {
private_key := "" //Key must be PEM encoded PKCS1 or PKCS8 private key
client_email := "test@testing.iam.gserviceaccount.com"
userid := "tester"

if _, err := GenerateCustomToken(userid, nil, client_email, private_key); err == nil {
t.Fatal(err)
}
}

func TestCustomAuthTokenDeveloperClaims(t *testing.T) {
private_key := "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXJ2PtihileBbe\nmgc4tckfZNf4ZXHYevhOJs7zj9lBxD4+CBvw9WWFBhnIvLhq42DoxPFz8jYbWsh9\nj7dFp9y0TDUiIIsvTm/KNJ9mL2ttgFiOZEdS9k8N1I9dDkM2UNi7WtGP03Tm0Abz\nfrvSCJKro3lr8+tzCzfV0rtkhIaurbOy3f+iy1Bh2dQ+m6bkc4IKFHeqKPEp46mp\nagGgxergN0WIHfhcjFXkL+GspcuRw8C+AX84GZHmefyYycXY1R0DkSWMTm5q1MUs\ny5rbiCNtHW/elXoVbnlvSka3+GM9HRFXrevF+BmJHk1AziOBy49R5fgmw92/LwNQ\n3KzJl5rBAgMBAAECggEAWov0TRrKJpE0prgSA/bVTsYE8j/XOrD94P4KKIzIdRoe\ny8Jj5/OOpv4bSdTKlAlfVnbT2uT7imWZbOZXzhPIGYTc86DYkq8i8ulUkA+y2WGj\nY0Gmlq6cNIjZUONYu/ooTCj7etkWILE5y63xY4JCH8PrrNf5pe/5rp5CSRpRCB/C\nZI1Arjy7ZUPaGypAH58gakDDBWIiSCRsFX+0bt5u+J+FWebcurYQ+Y+qdpJ6cKbZ\nen0AWHQroxpWw7dWwsSriUYroKJMKLt5zM/wOJ5N4qKVwpuJX6qWB7C6JyyOZaJY\nEM5oOdMl94/Ml3gUpyfWRwV2qJkSFsvwd895hOkrhQKBgQD30WauA0SiVcHQowu/\ngbszKGaWwkoELFhPxUrtNZrQdQYBBoqft5nEA0mzY5DSoDgs4SDTMJ8HlA79XOKd\nlqCBeKWxS10zGOIxx+qWPpkulRnQek1088ZBGBxDu8V+SVfEqH+sQLEN4H9lYNe0\nRCTxrLVGcv2bezv3rpC2vKFmQwKBgQDeQegi6a73UUJV3yYGM8VBfmZjUCGb5KdH\nH8b1nc+Ty7C0z7nXU1zizN9ZZaIVMivfSt8H2W+3ikQ4FY8f7DAAQmw2JFrvKb4N\n/nnQXGIcRfO/RdM8ui88Oh7uJgZrkE9SbaWoVlhzZOv64aLqi/TZAN5UstIpNLfA\nS9s2bz/EqwKBgQCkQBELMrVR1v8PtpE5y9V0ccmVEI8YNwANVxlzIT1L/tQM5/YH\nKBxtMzStBkfdoj25WTl1YFt3HWXV/bNheY1GYt2HJglOraZ2EifkjvbeTgp/CCDA\nbDYxvLY3GoQqUJgwivGcDICNTweA/O/a1fOajrrTR7HZVJOJdRULWPismwKBgDs1\njZT3chAayrQ7rVKLqioHdVlRuJJiOJn/Ai7eqrTx15JjoFuXrrAQ6hNTuvkwk3V5\n6a6ao2Ne50uVmrpjXmpDR7aourzp/uKVf3gdlFl53TSAcoTECN9fkGvbH2y6Vhdc\ndHxC/G9JXIBKae9X95Nz4sbnmIs3qxgEXVLEElXfAoGAMgmwfSWOcdBahUvpiwOu\nJ0vJH5rmPYtBoFdd418Ynji2O0/8R9N5gDshff7ns6NBL/u1OS23fESWs4Lv09Hh\nS/ExVyxe2sa1RyDVbljLH5+aLkpWCfiNEFGcJ0kyIucPzjHJLCC6dTKh84fSTPRm\nWRRCbVUmvLnwcpIpPMhcnTc=\n-----END PRIVATE KEY-----\n"
client_email := "test@testing.iam.gserviceaccount.com"
userid := "tester"

developerClaims := jws.Claims{}

developerClaims.Set("premium_account", true)

if _, err := GenerateCustomToken(userid, &developerClaims, client_email, private_key); err != nil {
t.Fatal(err)
}
}

func TestCustomAuthTokenDeveloperClaimsReserved(t *testing.T) {
private_key := "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXJ2PtihileBbe\nmgc4tckfZNf4ZXHYevhOJs7zj9lBxD4+CBvw9WWFBhnIvLhq42DoxPFz8jYbWsh9\nj7dFp9y0TDUiIIsvTm/KNJ9mL2ttgFiOZEdS9k8N1I9dDkM2UNi7WtGP03Tm0Abz\nfrvSCJKro3lr8+tzCzfV0rtkhIaurbOy3f+iy1Bh2dQ+m6bkc4IKFHeqKPEp46mp\nagGgxergN0WIHfhcjFXkL+GspcuRw8C+AX84GZHmefyYycXY1R0DkSWMTm5q1MUs\ny5rbiCNtHW/elXoVbnlvSka3+GM9HRFXrevF+BmJHk1AziOBy49R5fgmw92/LwNQ\n3KzJl5rBAgMBAAECggEAWov0TRrKJpE0prgSA/bVTsYE8j/XOrD94P4KKIzIdRoe\ny8Jj5/OOpv4bSdTKlAlfVnbT2uT7imWZbOZXzhPIGYTc86DYkq8i8ulUkA+y2WGj\nY0Gmlq6cNIjZUONYu/ooTCj7etkWILE5y63xY4JCH8PrrNf5pe/5rp5CSRpRCB/C\nZI1Arjy7ZUPaGypAH58gakDDBWIiSCRsFX+0bt5u+J+FWebcurYQ+Y+qdpJ6cKbZ\nen0AWHQroxpWw7dWwsSriUYroKJMKLt5zM/wOJ5N4qKVwpuJX6qWB7C6JyyOZaJY\nEM5oOdMl94/Ml3gUpyfWRwV2qJkSFsvwd895hOkrhQKBgQD30WauA0SiVcHQowu/\ngbszKGaWwkoELFhPxUrtNZrQdQYBBoqft5nEA0mzY5DSoDgs4SDTMJ8HlA79XOKd\nlqCBeKWxS10zGOIxx+qWPpkulRnQek1088ZBGBxDu8V+SVfEqH+sQLEN4H9lYNe0\nRCTxrLVGcv2bezv3rpC2vKFmQwKBgQDeQegi6a73UUJV3yYGM8VBfmZjUCGb5KdH\nH8b1nc+Ty7C0z7nXU1zizN9ZZaIVMivfSt8H2W+3ikQ4FY8f7DAAQmw2JFrvKb4N\n/nnQXGIcRfO/RdM8ui88Oh7uJgZrkE9SbaWoVlhzZOv64aLqi/TZAN5UstIpNLfA\nS9s2bz/EqwKBgQCkQBELMrVR1v8PtpE5y9V0ccmVEI8YNwANVxlzIT1L/tQM5/YH\nKBxtMzStBkfdoj25WTl1YFt3HWXV/bNheY1GYt2HJglOraZ2EifkjvbeTgp/CCDA\nbDYxvLY3GoQqUJgwivGcDICNTweA/O/a1fOajrrTR7HZVJOJdRULWPismwKBgDs1\njZT3chAayrQ7rVKLqioHdVlRuJJiOJn/Ai7eqrTx15JjoFuXrrAQ6hNTuvkwk3V5\n6a6ao2Ne50uVmrpjXmpDR7aourzp/uKVf3gdlFl53TSAcoTECN9fkGvbH2y6Vhdc\ndHxC/G9JXIBKae9X95Nz4sbnmIs3qxgEXVLEElXfAoGAMgmwfSWOcdBahUvpiwOu\nJ0vJH5rmPYtBoFdd418Ynji2O0/8R9N5gDshff7ns6NBL/u1OS23fESWs4Lv09Hh\nS/ExVyxe2sa1RyDVbljLH5+aLkpWCfiNEFGcJ0kyIucPzjHJLCC6dTKh84fSTPRm\nWRRCbVUmvLnwcpIpPMhcnTc=\n-----END PRIVATE KEY-----\n"
client_email := "test@testing.iam.gserviceaccount.com"
userid := "tester"

developerClaims := jws.Claims{}

developerClaims.Set("aud", "reserved")

if _, err := GenerateCustomToken(userid, &developerClaims, client_email, private_key); err == nil {
t.Fatal(err)
}
}

0 comments on commit ace23b7

Please sign in to comment.