Skip to content

Commit

Permalink
Merge dev into master
Browse files Browse the repository at this point in the history
  • Loading branch information
google-oss-bot committed Oct 22, 2020
2 parents cef91ac + 7f59540 commit 77177c7
Show file tree
Hide file tree
Showing 14 changed files with 459 additions and 76 deletions.
File renamed without changes.
File renamed without changes.
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ required to ensure that exported user records contain the password hashes of the
3. Click 'ADD ANOTHER ROLE' and choose 'Firebase Authentication Admin'.
4. Click 'SAVE'.

Some of the integration tests require an
[Identity Platform](https://cloud.google.com/identity-platform/) project with multi-tenancy
[enabled](https://cloud.google.com/identity-platform/docs/multi-tenancy-quickstart#enabling_multi-tenancy).
An existing Firebase project can be upgraded to an Identity Platform project without losing any
functionality via the
[Identity Platform Marketplace Page](https://console.cloud.google.com/customer-identity). Note that
charges may be incurred for active users beyond the Identity Platform free tier.

Now you can invoke the test suite as follows:

```bash
Expand Down
4 changes: 2 additions & 2 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ func NewClient(ctx context.Context, conf *internal.AuthConfig) (*Client, error)
// - If the SDK was initialized with service account credentials, uses the private key present in
// the credentials to sign tokens locally.
// - If a service account email was specified during initialization (via firebase.Config struct),
// calls the IAM service with that email to sign tokens remotely. See
// https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signBlob.
// calls the IAMCredentials service with that email to sign tokens remotely. See
// https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob.
// - If the code is deployed in the Google App Engine standard environment, uses the App Identity
// service to sign tokens. See https://cloud.google.com/appengine/docs/standard/go/reference#SignBytes.
// - If the code is deployed in a different GCP-managed environment (e.g. Google Compute Engine),
Expand Down
79 changes: 55 additions & 24 deletions auth/hash/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ import (
"firebase.google.com/go/v4/internal"
)

// InputOrderType specifies the order in which users' passwords/salts are hashed
type InputOrderType int

// Available InputOrderType values
const (
InputOrderUnspecified InputOrderType = iota
InputOrderSaltFirst
InputOrderPasswordFirst
)

// Bcrypt represents the BCRYPT hash algorithm.
//
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_bcrypt_hashed_passwords
Expand Down Expand Up @@ -96,12 +106,13 @@ func (s Scrypt) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_hmac_hashed_passwords
// for more details. Key is required.
type HMACMD5 struct {
Key []byte
Key []byte
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h HMACMD5) Config() (internal.HashConfig, error) {
return hmacConfig("HMAC_MD5", h.Key)
return hmacConfig("HMAC_MD5", h.Key, h.InputOrder)
}

// HMACSHA1 represents the HMAC SHA512 hash algorithm.
Expand All @@ -110,12 +121,13 @@ func (h HMACMD5) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_hmac_hashed_passwords
// for more details.
type HMACSHA1 struct {
Key []byte
Key []byte
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h HMACSHA1) Config() (internal.HashConfig, error) {
return hmacConfig("HMAC_SHA1", h.Key)
return hmacConfig("HMAC_SHA1", h.Key, h.InputOrder)
}

// HMACSHA256 represents the HMAC SHA512 hash algorithm.
Expand All @@ -124,12 +136,13 @@ func (h HMACSHA1) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_hmac_hashed_passwords
// for more details.
type HMACSHA256 struct {
Key []byte
Key []byte
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h HMACSHA256) Config() (internal.HashConfig, error) {
return hmacConfig("HMAC_SHA256", h.Key)
return hmacConfig("HMAC_SHA256", h.Key, h.InputOrder)
}

// HMACSHA512 represents the HMAC SHA512 hash algorithm.
Expand All @@ -138,12 +151,13 @@ func (h HMACSHA256) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_hmac_hashed_passwords
// for more details.
type HMACSHA512 struct {
Key []byte
Key []byte
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h HMACSHA512) Config() (internal.HashConfig, error) {
return hmacConfig("HMAC_SHA512", h.Key)
return hmacConfig("HMAC_SHA512", h.Key, h.InputOrder)
}

// MD5 represents the MD5 hash algorithm.
Expand All @@ -152,12 +166,13 @@ func (h HMACSHA512) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_md5_sha_and_pbkdf_hashed_passwords
// for more details.
type MD5 struct {
Rounds int
Rounds int
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h MD5) Config() (internal.HashConfig, error) {
return basicConfig("MD5", h.Rounds)
return basicConfig("MD5", h.Rounds, h.InputOrder)
}

// PBKDF2SHA256 represents the PBKDF2SHA256 hash algorithm.
Expand All @@ -171,7 +186,7 @@ type PBKDF2SHA256 struct {

// Config returns the validated hash configuration.
func (h PBKDF2SHA256) Config() (internal.HashConfig, error) {
return basicConfig("PBKDF2_SHA256", h.Rounds)
return basicConfig("PBKDF2_SHA256", h.Rounds, InputOrderUnspecified)
}

// PBKDFSHA1 represents the PBKDFSHA1 hash algorithm.
Expand All @@ -185,7 +200,7 @@ type PBKDFSHA1 struct {

// Config returns the validated hash configuration.
func (h PBKDFSHA1) Config() (internal.HashConfig, error) {
return basicConfig("PBKDF_SHA1", h.Rounds)
return basicConfig("PBKDF_SHA1", h.Rounds, InputOrderUnspecified)
}

// SHA1 represents the SHA1 hash algorithm.
Expand All @@ -194,12 +209,13 @@ func (h PBKDFSHA1) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_md5_sha_and_pbkdf_hashed_passwords
// for more details.
type SHA1 struct {
Rounds int
Rounds int
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h SHA1) Config() (internal.HashConfig, error) {
return basicConfig("SHA1", h.Rounds)
return basicConfig("SHA1", h.Rounds, h.InputOrder)
}

// SHA256 represents the SHA256 hash algorithm.
Expand All @@ -208,12 +224,13 @@ func (h SHA1) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_md5_sha_and_pbkdf_hashed_passwords
// for more details.
type SHA256 struct {
Rounds int
Rounds int
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h SHA256) Config() (internal.HashConfig, error) {
return basicConfig("SHA256", h.Rounds)
return basicConfig("SHA256", h.Rounds, h.InputOrder)
}

// SHA512 represents the SHA512 hash algorithm.
Expand All @@ -222,25 +239,32 @@ func (h SHA256) Config() (internal.HashConfig, error) {
// Refer to https://firebase.google.com/docs/auth/admin/import-users#import_users_with_md5_sha_and_pbkdf_hashed_passwords
// for more details.
type SHA512 struct {
Rounds int
Rounds int
InputOrder InputOrderType
}

// Config returns the validated hash configuration.
func (h SHA512) Config() (internal.HashConfig, error) {
return basicConfig("SHA512", h.Rounds)
return basicConfig("SHA512", h.Rounds, h.InputOrder)
}

func hmacConfig(name string, key []byte) (internal.HashConfig, error) {
func hmacConfig(name string, key []byte, order InputOrderType) (internal.HashConfig, error) {
if len(key) == 0 {
return nil, errors.New("signer key not specified")
}
return internal.HashConfig{
conf := internal.HashConfig{
"hashAlgorithm": name,
"signerKey": base64.RawURLEncoding.EncodeToString(key),
}, nil
}
if order == InputOrderSaltFirst {
conf["passwordHashOrder"] = "SALT_AND_PASSWORD"
} else if order == InputOrderPasswordFirst {
conf["passwordHashOrder"] = "PASSWORD_AND_SALT"
}
return conf, nil
}

func basicConfig(name string, rounds int) (internal.HashConfig, error) {
func basicConfig(name string, rounds int, order InputOrderType) (internal.HashConfig, error) {
minRounds := 0
maxRounds := 120000
switch name {
Expand All @@ -253,8 +277,15 @@ func basicConfig(name string, rounds int) (internal.HashConfig, error) {
if rounds < minRounds || maxRounds < rounds {
return nil, fmt.Errorf("rounds must be between %d and %d", minRounds, maxRounds)
}
return internal.HashConfig{

conf := internal.HashConfig{
"hashAlgorithm": name,
"rounds": rounds,
}, nil
}
if order == InputOrderSaltFirst {
conf["passwordHashOrder"] = "SALT_AND_PASSWORD"
} else if order == InputOrderPasswordFirst {
conf["passwordHashOrder"] = "PASSWORD_AND_SALT"
}
return conf, nil
}
Loading

0 comments on commit 77177c7

Please sign in to comment.