Files
amazon-token/token.go
2019-03-17 21:31:06 -07:00

346 lines
12 KiB
Go

package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
"github.com/google/uuid"
)
//Amazon account structs
type AmazonBearer struct {
CustomerId string `json:"customer_id"`
Extensions struct {
DeviceInfo struct {
DeviceSN string `json:"device_serial_number"`
DeviceType string `json:"device_type"`
DeviceName string `json:"device_name"`
} `json:"device_info"`
CustomerInfo struct {
Name string `json:"name"`
HomeRegion string `json:"home_region"`
AccountPool string `json:"account_pool"`
GivenName string `json:"given_name"`
UserId string `json:"user_id"`
} `json:"customer_info"`
} `json:"extensions"`
Tokens struct {
MacDMS struct {
ADPToken string `json:"adp_token"`
DevicePrivateKey string `json:"device_private_key"`
} `json:"mac_dms"`
StoreAuthCookie struct {
Cookie string `json:"cookie"`
} `json:"store_authentication_cookie"`
Bearer struct {
AccessToken string `json:"access_token"`
ExpiresIn string `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
} `json:"bearer"`
} `json:"tokens"`
}
type AmazonApi struct {
Payload struct {
AuthData struct {
Global string `json:"use_global_authentication"`
User struct {
UserId string `json:"user_id"`
Password string `json:"password"`
} `json:"user_id_password"`
AccessToken string `json:"access_token,omitempty"`
} `json:"auth_data"`
RegistrationData struct {
Domain string `json:"domain"`
Type string `json:"device_type"`
Serial string `json:"device_serial"`
AppName string `json:"app_name"`
AppVersion string `json:"app_version"`
Model string `json:"device_model"`
OSVersion string `json:"os_version"`
SoftwareVersion string `json:"software_version"`
} `json:"registration_data"`
RequestedToken []string `json:"requested_token_type"`
Cookies struct {
Domain string `json:"domain"`
Website []string `json:"website_cookies"`
} `json:"cookies"`
UserContext struct {
Frc string `json:"frc"`
} `json:"user_context_map"`
DeviceMetadata DeviceMetadata `json:"device_metadata"`
Extenstions []string `json:"requested_extensions"`
} `json:"api_payload"`
Headers struct {
Login string `json:"login"`
Refresh string `json:"refresh"`
Main string `json:"main"`
Instance string `json:"app_instance"`
MapVersion MapVersion `json:"map_version"`
} `json:"headers"`
}
type DeviceMetadata struct {
DeviceOS string `json:"device_os_family"`
DeviceType string `json:"device_type"`
DeviceSerial string `json:"device_serial"`
MacAddress string `json:"mac_address"`
IMEI string `json:"imei"`
Manufacturer string `json:"manufacturer"`
Model string `json:"model"`
OSVersion string `json:"os_version"`
AndroidID string `json:"android_id"`
BuildSerial string `json:"build_serial"`
Product string `json:"product"`
}
type MapVersion struct {
Version string `json:"current_version"`
Package string `json:"package_name"`
Platform string `json:"platform"`
}
type RefreshPayload struct {
AppName string `json:"app_name"`
AppVersion string `json:"app_version"`
SourceType string `json:"source_token_type"`
Token string `json:"source_token"`
RequestedType string `json:"requested_token_type"`
MetaData DeviceMetadata `json:"device_metadata"`
MapVersion MapVersion `json:"map_version"`
}
type LoginResponse struct {
Response struct {
Success *AmazonBearer `json:"success"`
Challenge *struct {
Reason string `json:"challenge_reason"`
URI string `json:"uri"`
Method string `json:"required_authentication_method"`
Context string `json:"challenge_context"`
} `json:"challenge"`
} `json:"response"`
}
var (
TokenExpire time.Time
api = new(AmazonApi)
bearer = new(AmazonBearer)
)
func (bearer *AmazonBearer) Save(expiretime time.Time, acctpath string) {
bearer_file, _ := os.Create(path.Join(acctpath, "amazon-bearer.json"))
json.NewEncoder(bearer_file).Encode(bearer)
bearer_file.Close()
_ = os.Chtimes(".amazon-bearer", time.Now().Local(), expiretime.Add(-1*time.Hour))
}
func (api *AmazonApi) Load(acctpath string) {
api_file, err := os.Open(path.Join(acctpath, "amazon-api.json"))
if err != nil {
api.New()
} else {
json.NewDecoder(api_file).Decode(&api)
api_file.Close()
}
}
func login() {
b := new(bytes.Buffer)
json.NewEncoder(b).Encode(api.Payload)
client := &http.Client{}
req, _ := http.NewRequest("POST", "https://api.amazon.com/auth/register", b)
uuid, _ := uuid.NewRandom()
req.Header.Add("X-Amzn-RequestId", uuid.String())
req.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req.Header.Add("User-Agent", api.Headers.Login)
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
}
var response LoginResponse
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(&response)
if response.Response.Success != nil {
bearer = response.Response.Success
currenttime := time.Now().Local()
expire, _ := strconv.Atoi(bearer.Tokens.Bearer.ExpiresIn)
TokenExpire = currenttime.Add(time.Second * time.Duration(expire))
fmt.Println("Login Succeeded for Device: " + bearer.Extensions.DeviceInfo.DeviceName)
} else if response.Response.Challenge != nil {
scanner := bufio.NewScanner(os.Stdin)
cookieJar, _ := cookiejar.New(nil)
client2 := &http.Client{Jar: cookieJar}
uri, _ := url.Parse(response.Response.Challenge.URI)
data := uri.Query()
data.Add("openid.pape.max_auth_age", "0")
data.Add("openid.identity", "http://specs.openid.net/auth/2.0/identifier_select")
data.Add("accountStatusPolicy", "P1")
data.Add("language", "en_US")
data.Add("openid.return_to", "https://www.amazon.com/ap/maplanding")
data.Add("openid.assoc_handle", "amzn_device_na")
data.Add("openid.oa2.response_type", "token")
data.Add("openid.mode", "checkid_setup")
data.Add("openid.ns.pape", "http://specs.openid.net/extensions/pape/1.0")
data.Add("openid.ns.oa2", "http://www.amazon.com/ap/ext/oauth/2")
data.Add("openid.oa2.scope", "device_auth_access")
data.Add("openid.claimed_id", "http://specs.openid.net/auth/2.0/identifier_select")
data.Add("openid.oa2.client_id", "device:"+api.Payload.RegistrationData.Serial)
data.Add("disableLoginPrepopulate", "0")
data.Add("openid.ns", "http://specs.openid.net/auth/2.0")
uri.RawQuery = data.Encode()
req2, _ := http.NewRequest("GET", uri.String(), nil)
req2.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req2.Header.Add("User-Agent", api.Headers.Login)
resp2, err := client2.Do(req2)
if err != nil {
fmt.Println(err)
}
referer := resp2.Request.URL.String()
fmt.Println(referer)
defer resp2.Body.Close()
body, err := ioutil.ReadAll(resp2.Body)
if err != nil {
fmt.Println(err)
}
client3 := &http.Client{Jar: cookieJar, CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}}
if response.Response.Challenge.Reason == "MissingRequiredAuthenticationData" {
if response.Response.Challenge.Method == "OTPCode" {
fmt.Println("Account set for 2 Factor Authentication")
fmt.Print("Enter One Time Code: ")
scanner.Scan()
otp := scanner.Text()
re := regexp.MustCompile(`<input type="hidden" name="(.+?)" value="(.+?)"`)
stuff := re.FindAllStringSubmatch(string(body), -1)
data2 := url.Values{}
for _, value := range stuff {
data2.Set(value[1], value[2])
}
data2.Set("otpCode", otp)
data2.Set("rememberDevice", "")
req3, _ := http.NewRequest("POST", "https://www.amazon.com/ap/signin", strings.NewReader(data2.Encode()))
req3.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req3.Header.Add("User-Agent", api.Headers.Login)
req3.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp3, err := client3.Do(req3)
if err != nil {
fmt.Println(err)
}
if resp3.StatusCode == 302 {
redir := resp3.Header.Get("Location")
if strings.Contains(redir, "maplanding") {
fmt.Println("2FA Authentication Successful")
redir_url, _ := url.Parse(redir)
data3 := redir_url.Query()
token := data3.Get("openid.oa2.access_token")
api.Payload.AuthData.AccessToken = token
login()
}
}
} else {
fmt.Println(response.Response.Challenge)
fmt.Println("MissingRequiredAuthenticationData - Unknown Method")
os.Exit(0)
}
} else if response.Response.Challenge.Reason == "HandleOnWebView" {
fmt.Println("HandleOnWebView")
if strings.Contains(referer, "CAPTCHA") {
fmt.Println("CAPTCHA Verification Required", "Sorry we can't currently handle that")
os.Exit(0)
} else {
fmt.Println("Verification Code Required")
re := regexp.MustCompile(`<input type="hidden" name="(.+?)" value="(.+?)"`)
stuff := re.FindAllStringSubmatch(string(body), -1)
data2 := url.Values{}
for _, value := range stuff {
data2.Set(value[1], value[2])
}
data2.Set("option", "email")
req3, _ := http.NewRequest("POST", "https://www.amazon.com/ap/cvf/verify", strings.NewReader(data2.Encode()))
req3.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req3.Header.Add("User-Agent", api.Headers.Login)
req3.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp3, err := client2.Do(req3)
if err != nil {
fmt.Println(err)
}
if resp3.StatusCode == 200 {
fmt.Println("Code Sent to Email")
fmt.Print("Verification Code: ")
scanner.Scan()
data2.Del("option")
data2.Set("code", scanner.Text())
data2.Set("action", "code")
req4, _ := http.NewRequest("POST", "https://www.amazon.com/ap/cvf/verify", strings.NewReader(data2.Encode()))
req4.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req4.Header.Add("User-Agent", api.Headers.Login)
req4.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp4, err := client3.Do(req4)
if err != nil {
fmt.Println(err)
}
if resp4.StatusCode == 302 {
redir := resp4.Header.Get("Location")
if strings.Contains(redir, "signin") || strings.Contains(redir, "auth") {
req5, _ := http.NewRequest("GET", redir, nil)
req5.Header.Add("x-amzn-identity-auth-domain", ".amazon.com")
req5.Header.Add("User-Agent", api.Headers.Login)
resp5, err := client3.Do(req5)
if err != nil {
fmt.Println(err)
}
if resp5.StatusCode == 302 {
redir2 := resp5.Header.Get("Location")
if strings.Contains(redir2, "maplanding") {
fmt.Println("Verification Successful")
redir_url, _ := url.Parse(redir2)
data3 := redir_url.Query()
token := data3.Get("openid.oa2.access_token")
api.Payload.AuthData.AccessToken = token
login()
} else {
fmt.Println("Error With Redirect 2", redir)
os.Exit(0)
}
} else {
fmt.Printf("%d:Error Logging In 2", resp4.StatusCode)
os.Exit(0)
}
} else {
fmt.Println("Error With Redirect", redir)
os.Exit(0)
}
} else {
fmt.Printf("%d:Error Logging In", resp4.StatusCode)
os.Exit(0)
}
}
}
} else if response.Response.Challenge.Reason == "AuthenticationFailed" {
fmt.Println("Login Failed - Incorrect User/Pass")
os.Exit(0)
} else {
fmt.Println(response.Response.Challenge)
fmt.Println("Login Failed due to Challenge")
os.Exit(0)
}
} else {
fmt.Println("Login Failed for unknown reason")
fmt.Println(resp.Status)
io.Copy(os.Stdout, resp.Body)
os.Exit(0)
}
}