hydroxide-push/protonmail/auth.go

154 lines
2.7 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
}
2017-08-22 10:21:50 +03:00
type AuthInfo struct {
TwoFactor int
version int
modulus string
serverEphemeral string
salt string
srpSession string
}
2017-08-22 01:04:16 +03:00
type AuthInfoResp struct {
resp
2017-08-22 10:21:50 +03:00
AuthInfo
2017-08-22 01:04:16 +03:00
Version int
Modulus string
ServerEphemeral string
Salt string
SRPSession string
}
2017-08-22 10:21:50 +03:00
func (resp *AuthInfoResp) authInfo() *AuthInfo {
info := &resp.AuthInfo
info.version = resp.Version
info.modulus = resp.Modulus
info.serverEphemeral = resp.ServerEphemeral
info.salt = resp.Salt
info.srpSession = resp.SRPSession
return info
2017-08-22 01:04:16 +03:00
}
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
}
2017-08-22 10:21:50 +03:00
return respData.authInfo(), nil
2017-08-22 01:04:16 +03:00
}
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
)
2017-08-22 10:41:47 +03:00
type Auth struct {
2017-08-22 01:04:16 +03:00
AccessToken string
ExpiresIn int
TokenType string
Scope string
UID string `json:"Uid"`
RefreshToken string
EventID string
PasswordMode PasswordMode
2017-08-22 10:41:47 +03:00
privateKey string
keySalt string
}
type authResp struct {
resp
Auth
ServerProof string
2017-08-22 01:04:16 +03:00
PrivateKey string
KeySalt string
}
2017-08-22 10:41:47 +03:00
func (resp *authResp) auth() *Auth {
auth := &resp.Auth
auth.privateKey = resp.PrivateKey
auth.keySalt = resp.KeySalt
return auth
}
func (c *Client) Auth(username, password, twoFactorCode string, info *AuthInfo) (*Auth, error) {
2017-08-22 01:04:16 +03:00
if info == nil {
var err error
if info, err = c.AuthInfo(username); err != nil {
2017-08-22 10:41:47 +03:00
return nil, err
2017-08-22 01:04:16 +03:00
}
}
log.Printf("%#v\n", info)
proofs, err := srp([]byte(password), info)
if err != nil {
2017-08-22 10:41:47 +03:00
return nil, err
2017-08-22 01:04:16 +03:00
}
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,
}
req, err := c.newJSONRequest(http.MethodPost, "/auth", reqData)
if err != nil {
2017-08-22 10:41:47 +03:00
return nil, err
2017-08-22 01:04:16 +03:00
}
var respData authResp
if err := c.doJSON(req, &respData); err != nil {
2017-08-22 10:41:47 +03:00
return nil, err
2017-08-22 01:04:16 +03:00
}
2017-08-22 10:41:47 +03:00
log.Printf("%+v\n", respData)
2017-08-22 01:04:16 +03:00
if err := proofs.VerifyServerProof(respData.ServerProof); err != nil {
2017-08-22 10:41:47 +03:00
return nil, err
2017-08-22 01:04:16 +03:00
}
2017-08-22 10:41:47 +03:00
return respData.auth(), nil
2017-08-22 01:04:16 +03:00
}