user: fix password info JSON encoding to survive round trips

PasswordInfos are marshaled when storing them in the database as
part of the local connector. However, the custom unmarsheler
defined could not unmarshal the standard marshling of this struct.

Add a struct tag to the Password field to correct this.

Closes #332
This commit is contained in:
Eric Chiang 2016-02-23 15:36:40 -08:00
parent f51125f555
commit 221a1ad7a0
3 changed files with 46 additions and 5 deletions

View file

@ -61,7 +61,7 @@ func TestNewConnectorConfigFromMap(t *testing.T) {
"type": "local", "type": "local",
"id": "foo", "id": "foo",
"passwordInfos": []map[string]string{ "passwordInfos": []map[string]string{
{"userId": "abc", "passwordHash": "PING"}, {"userId": "abc", "passwordHash": "UElORw=="}, // []byte is base64 encoded when using json.Marshasl
{"userId": "271", "passwordPlaintext": "pong"}, {"userId": "271", "passwordPlaintext": "pong"},
}, },
}, },

View file

@ -53,9 +53,9 @@ func NewPasswordFromPlaintext(plaintext string) (Password, error) {
type PasswordInfo struct { type PasswordInfo struct {
UserID string UserID string
Password Password Password Password `json:"passwordHash"`
PasswordExpires time.Time PasswordExpires time.Time `json:"passwordExpires"`
} }
func (p PasswordInfo) Authenticate(plaintext string) (*oidc.Identity, error) { func (p PasswordInfo) Authenticate(plaintext string) (*oidc.Identity, error) {
@ -86,7 +86,7 @@ type PasswordInfoRepo interface {
func (u *PasswordInfo) UnmarshalJSON(data []byte) error { func (u *PasswordInfo) UnmarshalJSON(data []byte) error {
var dec struct { var dec struct {
UserID string `json:"userId"` UserID string `json:"userId"`
PasswordHash string `json:"passwordHash"` PasswordHash []byte `json:"passwordHash"`
PasswordPlaintext string `json:"passwordPlaintext"` PasswordPlaintext string `json:"passwordPlaintext"`
PasswordExpires time.Time `json:"passwordExpires"` PasswordExpires time.Time `json:"passwordExpires"`
} }
@ -98,7 +98,9 @@ func (u *PasswordInfo) UnmarshalJSON(data []byte) error {
u.UserID = dec.UserID u.UserID = dec.UserID
u.PasswordExpires = dec.PasswordExpires if !dec.PasswordExpires.IsZero() {
u.PasswordExpires = dec.PasswordExpires
}
if len(dec.PasswordHash) != 0 { if len(dec.PasswordHash) != 0 {
if dec.PasswordPlaintext != "" { if dec.PasswordPlaintext != "" {

View file

@ -1,6 +1,7 @@
package user package user
import ( import (
"encoding/json"
"net/url" "net/url"
"testing" "testing"
"time" "time"
@ -13,6 +14,44 @@ import (
"github.com/coreos/go-oidc/key" "github.com/coreos/go-oidc/key"
) )
func TestPasswordMarshaling(t *testing.T) {
hashPassword := func(s string) []byte {
data, err := DefaultPasswordHasher(s)
if err != nil {
t.Fatalf("Failed to hash password: %v", err)
}
return data
}
tests := []PasswordInfo{
{
UserID: "mrpink",
Password: hashPassword("mrpinks-password"),
},
{
UserID: "mrorange",
Password: hashPassword("mroranges-password"),
PasswordExpires: time.Now().Add(time.Hour),
},
}
for i, tt := range tests {
data, err := json.Marshal(tt)
if err != nil {
t.Errorf("case %d: failed to marshal password info: %v", i, err)
continue
}
var p PasswordInfo
if err := json.Unmarshal(data, &p); err != nil {
t.Errorf("case %d: failed to unmarshal password info: %v", i, err)
continue
}
if diff := pretty.Compare(tt, p); diff != "" {
t.Errorf("case %d: password info did not survive JSON marshal round trip: %s", i, diff)
}
}
}
func TestNewPasswordFromHash(t *testing.T) { func TestNewPasswordFromHash(t *testing.T) {
tests := []string{ tests := []string{
"test", "test",