Skip to content

Commit

Permalink
Add login method to cli and sdk.
Browse files Browse the repository at this point in the history
  • Loading branch information
Levi Sky authored and galxy25 committed Aug 21, 2020
1 parent bae2cb4 commit 227654d
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ lint:
build:
go build -o ${BINARY} ./cmd/${BINARY}

# Target for building and moving the binary to the local system execution path
install:
go install ./cmd/${BINARY}

# target for tagging and publishing a new version of the SDK
# run like make version=X.Y.Z
version:
Expand Down
121 changes: 121 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,3 +904,124 @@ func (c *ToznySDKV3) Register(ctx context.Context, name string, email string, pa
}
return createResponse, nil
}

// Login derives the needed keys and fetches an active account session
func (c *ToznySDKV3) Login(ctx context.Context, email string, password string, salt string, apiEndpoint string) (Account, error) {
var account Account
var err error
var challenge Challenge
apiHost := c.APIEndpoint
if apiEndpoint != "" {
apiHost = apiEndpoint
}
body := map[string]string{}
body["email"] = email
path := apiHost + "/v1/account/challenge"
request, err := e3dbClients.CreateRequest("POST", path, body)
if err != nil {
return account, e3dbClients.NewError(err.Error(), path, 0)
}
err = e3dbClients.MakePublicCall(ctx, request, &challenge)
if err != nil {
return account, fmt.Errorf("initiating login challenge: %v", err)
}
var authSalt []byte
if salt != "paper" {
authSalt, err = base64.RawURLEncoding.DecodeString(challenge.AuthSalt)
} else {
authSalt, err = base64.RawURLEncoding.DecodeString(challenge.PaperAuthSalt)
}
if err != nil {
return account, fmt.Errorf("decoding salt: %v", err)
}
_, privateKey := e3dbClients.DeriveSigningKey([]byte(password), authSalt, e3dbClients.AccountDerivationRounds)
challengeBytes, err := base64.RawURLEncoding.DecodeString(challenge.Challenge)
if err != nil {
return account, fmt.Errorf("decoding signature: %v", err)
}
// challenge.challenge, sigKeys.privateKey
signatureBytes := e3dbClients.Sign(challengeBytes, privateKey)
signature := base64.RawURLEncoding.EncodeToString(signatureBytes)
body["challenge"] = challenge.Challenge
body["response"] = signature
if salt != "paper" {
body["keyid"] = "password"
} else {
body["keyid"] = "paper"
}
path = apiHost + "/v1/account/auth"
request, err = e3dbClients.CreateRequest("POST", path, body)
if err != nil {
return account, e3dbClients.NewError(err.Error(), path, 0)
}
var authResponse AuthResponse
err = e3dbClients.MakePublicCall(ctx, request, &authResponse)
if err != nil {
return account, fmt.Errorf("error %v initiating login challenge %+v", err, request)
}
var meta ProfileMeta
accountToken := authResponse.Token
path = apiHost + "/v1/account/profile/meta"
request, err = e3dbClients.CreateRequest("GET", path, nil)
if err != nil {
return account, e3dbClients.NewError(err.Error(), path, 0)
}
err = e3dbClients.MakeProxiedUserCall(ctx, accountToken, request, &meta)
if err != nil {
return account, fmt.Errorf("updating profile meta: %v", err)
}
var encSalt []byte
if salt != "paper" {
encSalt, err = base64.RawURLEncoding.DecodeString(authResponse.Profile.EncodingSalt)
} else {
encSalt, err = base64.RawURLEncoding.DecodeString(authResponse.Profile.PaperEncodingSalt)
}
if err != nil {
return account, fmt.Errorf("decoding salt: %v", err)
}
encKey := e3dbClients.DeriveSymmetricKey([]byte(password), encSalt, e3dbClients.AccountDerivationRounds)
var encCipher string
if salt != "paper" {
encCipher = meta.BackupClient
} else {
encCipher = meta.PaperBackup
}
var clientConfig ClientConfig
clientJSON, err := e3dbClients.Decrypt(encCipher, e3dbClients.MakeSymmetricKey(encKey[:]))
if err != nil {
return account, fmt.Errorf("decrypting client credentials: %v", err)
}
err = json.Unmarshal(clientJSON, &clientConfig)
if err != nil {
return account, fmt.Errorf("decoding client credentials: %v", err)
}

var accountClientConfig = e3dbClients.ClientConfig{
Host: apiHost,
AuthNHost: apiHost,
ClientID: clientConfig.ClientID,
APIKey: clientConfig.APIKeyID,
APISecret: clientConfig.APISecret,
SigningKeys: e3dbClients.SigningKeys{
Private: e3dbClients.Key{
Material: clientConfig.PrivateSigningKey,
Type: e3dbClients.DefaultSigningKeyType},
Public: e3dbClients.Key{
Material: clientConfig.PublicSigningKey,
Type: e3dbClients.DefaultSigningKeyType},
},
EncryptionKeys: e3dbClients.EncryptionKeys{
Private: e3dbClients.Key{
Material: clientConfig.PrivateKey,
Type: e3dbClients.DefaultEncryptionKeyType},
Public: e3dbClients.Key{
Material: clientConfig.PublicKey,
Type: e3dbClients.DefaultEncryptionKeyType},
},
}
mainClient := accountClient.New(accountClientConfig)
account.Client = &mainClient
account.Token = accountToken
account.Config = clientConfig
return account, nil
}
49 changes: 47 additions & 2 deletions cmd/e3db/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,6 @@ func main() {
options.Logging = app.BoolOpt("d debug", false, "enable debug logging")
options.Profile = app.StringOpt("p profile", "", "e3db configuration profile")

app.Command("signup", "signup for a new account", cmdSignup)
app.Command("register", "register a client", cmdRegister)
app.Command("info", "get client information", cmdInfo)
app.Command("ls", "list records", cmdList)
Expand All @@ -631,6 +630,8 @@ func main() {
cmd.Command("write", "write a small file", cmdWriteFile)
})
app.Command("lsrealms", "list realms", cmdListRealms)
app.Command("signup", "signup for a new account", cmdSignup)
app.Command("login", "login to fetch credentials and account token", cmdLogin)
app.Run(os.Args)
}

Expand Down Expand Up @@ -718,6 +719,50 @@ func cmdSignup(cmd *cli.Cmd) {
if err != nil {
dieErr(err)
}
fmt.Printf("\nCreated Account %+v\n", createdAccount)
fmt.Printf("Created Account %+v\n", createdAccount)
}
}

func cmdLogin(cmd *cli.Cmd) {
accountUsername := cmd.String(cli.StringArg{
Name: "ACCOUNT_EMAIL",
Desc: "Account username",
Value: "",
HideValue: true,
})
accountPassword := cmd.String(cli.StringArg{
Name: "ACCOUNT_PASSWORD",
Desc: "Account password",
Value: "",
HideValue: true,
})

loginEndpoint := cmd.String(cli.StringArg{
Name: "ENDPOINT",
Desc: "Endpoint to use for attempting the login password",
Value: "",
HideValue: true,
})

loginType := cmd.String(cli.StringArg{
Name: "LOGIN_TYPE",
Desc: "Login type. Valid values are `password` or `paper`",
Value: "password",
HideValue: false,
})

cmd.Spec = "[OPTIONS] [ACCOUNT_EMAIL] [ACCOUNT_PASSWORD] [ENDPOINT] [LOGIN_TYPE]"

cmd.Action = func() {
sdk, err := e3db.GetSDKV3(fmt.Sprintf(e3db.ProfileInterpolationConfigFilePath, *options.Profile))
if err != nil {
dieErr(err)
}
ctx := context.Background()
accountSession, err := sdk.Login(ctx, *accountUsername, *accountPassword, *loginType, *loginEndpoint)
if err != nil {
dieErr(err)
}
fmt.Printf("Account Session Token: %+v\n", accountSession.Token)
}
}

0 comments on commit 227654d

Please sign in to comment.