hydroxide-push/protonmail/auth.go

138 lines
2.4 KiB
Go
Raw Normal View History

2017-08-22 01:04:16 +03:00
package protonmail
import (
"encoding/base64"
"net/http"
"log"
)
type authInfoReq struct {
ClientID string
ClientSecret string
Username string
}
type AuthInfoResp struct {
resp
Version int
TwoFactor int
Modulus string
ServerEphemeral string
Salt string
SRPSession string
}
type AuthInfo struct {
TwoFactor int
version int
modulus string
serverEphemeral string
salt string
srpSession string
}
func (c *Client) AuthInfo(username string) (*AuthInfo, error) {
reqData := &authInfoReq{
ClientID: c.ClientID,
ClientSecret: c.ClientSecret,
Username: username,
}
req, err := c.newJSONRequest(http.MethodPost, "/auth/info", reqData)
if err != nil {
return nil, err
}
var respData AuthInfoResp
if err := c.doJSON(req, &respData); err != nil {
return nil, err
}
return &AuthInfo{
TwoFactor: respData.TwoFactor,
version: respData.Version,
modulus: respData.Modulus,
serverEphemeral: respData.ServerEphemeral,
salt: respData.Salt,
srpSession: respData.SRPSession,
}, nil
}
type authReq struct {
ClientID string
ClientSecret string
Username string
SRPSession string
ClientEphemeral string
ClientProof string
TwoFactorCode string
}
type PasswordMode int
const (
PasswordSingle PasswordMode = 1
PasswordTwo = 2
)
type authResp struct {
resp
AccessToken string
ExpiresIn int
TokenType string
Scope string
UID string `json:"Uid"`
RefreshToken string
EventID string
ServerProof string
PasswordMode PasswordMode
PrivateKey string
KeySalt string
}
func (c *Client) Auth(username, password, twoFactorCode string, info *AuthInfo) error {
if info == nil {
var err error
if info, err = c.AuthInfo(username); err != nil {
return err
}
}
log.Printf("%#v\n", info)
proofs, err := srp([]byte(password), info)
if err != nil {
return err
}
reqData := &authReq{
ClientID: c.ClientID,
ClientSecret: c.ClientSecret,
Username: username,
SRPSession: info.srpSession,
ClientEphemeral: base64.StdEncoding.EncodeToString(proofs.clientEphemeral),
ClientProof: base64.StdEncoding.EncodeToString(proofs.clientProof),
TwoFactorCode: twoFactorCode,
}
log.Printf("%#v\n", reqData)
req, err := c.newJSONRequest(http.MethodPost, "/auth", reqData)
if err != nil {
return err
}
var respData authResp
if err := c.doJSON(req, &respData); err != nil {
return err
}
log.Printf("%#v\n", respData)
if err := proofs.VerifyServerProof(respData.ServerProof); err != nil {
return err
}
return nil
}