hydroxide-push/protonmail/auth.go

152 lines
2.9 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 {
2017-08-22 11:16:20 +03:00
ClientID string
2017-08-22 01:04:16 +03:00
ClientSecret string
2017-08-22 11:16:20 +03:00
Username string
2017-08-22 01:04:16 +03:00
}
2017-08-22 10:21:50 +03:00
type AuthInfo struct {
2017-08-22 11:16:20 +03:00
TwoFactor int
version int
modulus string
2017-08-22 10:21:50 +03:00
serverEphemeral string
2017-08-22 11:16:20 +03:00
salt string
srpSession string
2017-08-22 10:21:50 +03:00
}
2017-08-22 01:04:16 +03:00
type AuthInfoResp struct {
resp
2017-08-22 10:21:50 +03:00
AuthInfo
2017-08-22 11:16:20 +03:00
Version int
Modulus string
2017-08-22 01:04:16 +03:00
ServerEphemeral string
2017-08-22 11:16:20 +03:00
Salt string
SRPSession string
2017-08-22 01:04:16 +03:00
}
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{
2017-08-22 11:16:20 +03:00
ClientID: c.ClientID,
2017-08-22 01:04:16 +03:00
ClientSecret: c.ClientSecret,
2017-08-22 11:16:20 +03:00
Username: username,
2017-08-22 01:04:16 +03:00
}
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 {
2017-08-22 11:16:20 +03:00
ClientID string
ClientSecret string
Username string
SRPSession string
2017-08-22 01:04:16 +03:00
ClientEphemeral string
2017-08-22 11:16:20 +03:00
ClientProof string
TwoFactorCode string
2017-08-22 01:04:16 +03:00
}
type PasswordMode int
const (
PasswordSingle PasswordMode = 1
2017-08-22 11:16:20 +03:00
PasswordTwo = 2
2017-08-22 01:04:16 +03:00
)
2017-08-22 10:41:47 +03:00
type Auth struct {
2017-08-22 11:16:20 +03:00
AccessToken string
ExpiresIn int
TokenType string
Scope string
UID string `json:"Uid"`
2017-08-22 01:04:16 +03:00
RefreshToken string
2017-08-22 11:16:20 +03:00
EventID string
2017-08-22 01:04:16 +03:00
PasswordMode PasswordMode
2017-08-22 10:41:47 +03:00
privateKey string
2017-08-22 11:16:20 +03:00
keySalt string
2017-08-22 10:41:47 +03:00
}
type authResp struct {
resp
Auth
ServerProof string
2017-08-22 11:16:20 +03:00
PrivateKey string
KeySalt string
2017-08-22 01:04:16 +03:00
}
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
}
}
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{
2017-08-22 11:16:20 +03:00
ClientID: c.ClientID,
ClientSecret: c.ClientSecret,
Username: username,
SRPSession: info.srpSession,
2017-08-22 01:04:16 +03:00
ClientEphemeral: base64.StdEncoding.EncodeToString(proofs.clientEphemeral),
2017-08-22 11:16:20 +03:00
ClientProof: base64.StdEncoding.EncodeToString(proofs.clientProof),
TwoFactorCode: twoFactorCode,
2017-08-22 01:04:16 +03:00
}
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
}