steamauth

package module
v0.0.0-...-5d6382d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2022 License: MIT Imports: 22 Imported by: 1

README

SteamAuth

Blatently ported, warts and all from https://github.com/geel9/SteamAuth

A Go library for logging into Steam with SteamGuard support.

Functionality

Currently, like the original, this library can:

  • Generate login codes for a given shared secret
  • Login to a user account
  • Link and activate a new mobile authenticator to a user account after logging in
  • Remove itself from an account
  • Fetch, accept, and deny mobile confirmations

Usage Notes

If you already have a SharedSecret just instantiate a SteamGuardAccount and call GenerateSteamGuardCode()

To remove the authenticator from your account you will need a working session (so log in with UserLogin or load a saved SteamGuardAccount json blob)

Usage

Authenticating
 auth := steamauth.NewUserLogin("username", "password")
 res, err := auth.DoLogin()
 // err usually means something went wrong in the library or connecting to steam
 switch res {
 case steamauth.NeedCaptcha:
  fmt.Printf("Requires captcha: %s\n", userLogin.CaptchaURL())
 case steamauth.Need2FA:
  fmt.Println("Need two factor code, get this from SteamGuard on your phone (or SteamGuardAccount if it's registered)")
 case steamauth.NeedEmail:
  fmt.Println("Code was sent to your email")
 case steamauth.LoginOkay:
  fmt.Println("Logged in!")
 }
Begin registration
 linker := steamauth.NewAuthenticatorLinker(userLogin.Session)
 linkres, err := linker.AddAuthenticator()
 // Again err usually means something went wrong in the library or connecting to steam
 switch linkres {
 case steamauth.MustProvidePhoneNumber:
  fmt.Println("Account doesn't have a phone number associated with it and you didn't provide one")
 case steamauth.MustRemovePhoneNumber:
  fmt.Println("Account already has a phone number associated with it and you provided one")
 case steamauth.AwaitingFinalization:
  fmt.Println("A message has been sent to the given mobile number, call FinalizeAddAuthenticator(smscode)")
 }
Finalize registration
 finres, err := linker.FinalizeAddAuthenticator(code)
 switch finres {
 case steamauth.BadSMSCode:
  fmt.Println("You done typoed son")
 case steamauth.UnableToGenerateCorrectCodes:
  fmt.Println("Steam doesn't like us, even after 30 tries")
 case steamauth.Success
  fmt.Println("Everything is awsome")
 }
Save state

Once you've finalized your registration you should absolutly save a copy of the SteamGuardAccount instance

 fmt.Println(linker.LinkedAccount.Export())

Tips

Proxy

Go nativly supports proxy from environment for http requests with no code modification

 export HTTP_PROXY="http://proxyIp:proxyPort"

or

 os.Setenv("HTTP_PROXY", "http://proxyIp:proxyPort")

Will do exactly what you expect it to do.

Example

Look in examples for an example that should authenticate and register itself with a given account

Documentation

Index

Constants

This section is empty.

Variables

View Source
var APIEndpoints = struct {
	SteamAPIBase       *url.URL
	CommunityBase      *url.URL
	TwoFactorTimeQuery *url.URL
}{
	SteamAPIBase:       &url.URL{Scheme: "https", Host: "api.steampowered.com"},
	CommunityBase:      &url.URL{Scheme: "https", Host: "steamcommunity.com"},
	TwoFactorTimeQuery: &url.URL{Scheme: "https", Host: "api.steampowered.com", Path: "/ITwoFactorService/QueryTime/v0001"},
}

APIEndpoints is storage for a bunch of common endpoints

View Source
var TimeAligner = &timeAligner{}

TimeAligner is used to synchronise your local time to the time in steamservers so that the SteamGuard codes generated match the expectations of Steam

Functions

func LogCookies

func LogCookies(doit bool)

LogCookies enable/disable

func LogRequests

func LogRequests(doit bool)

LogRequests enable/disable

func LogResponses

func LogResponses(doit bool)

LogResponses enable/disable

func SetLogger

func SetLogger(logger logLogger)

SetLogger to be used for logging

func SteamWeb

func SteamWeb() *steamWeb

SteamWeb returns a convenient chainable steamWeb object that allows you to perform requests against the steam API with a simple sequence of method calls.

Types

type AddAuthenticatorResponse

type AddAuthenticatorResponse struct {
	Response SteamGuardAccount `json:"response"`
}

type AddPhoneResponse

type AddPhoneResponse struct {
	Success bool `json:"success"`
}

type AuthenticatorLinker

type AuthenticatorLinker struct {
	PhoneNumber   string
	DeviceID      string
	LinkedAccount SteamGuardAccount
	Finalized     bool
	// contains filtered or unexported fields
}

AuthenticatorLinker will link this Authenticator to your steam account Once successfully linked LinkedAccount contains a SteamGuardAccount object and save it for reuse in future requests

func NewAuthenticatorLinker

func NewAuthenticatorLinker(session *SessionData) *AuthenticatorLinker

NewAuthenticatorLinker will create an account linker

Pass it the SessionData from a logged in instance of a UserLogin structure.

func (*AuthenticatorLinker) AddAuthenticator

func (al *AuthenticatorLinker) AddAuthenticator() (LinkResult, error)

AddAuthenticator will configure your account for steamguard, create and link an instance of a SteamGuardAccount structure

If everything goes well you will get a LinkResult of AwaitingFinalization which means you must collect the code sent to the linked phone and submit it with `FinalizeAddAuthenticator`

func (*AuthenticatorLinker) FinalizeAddAuthenticator

func (al *AuthenticatorLinker) FinalizeAddAuthenticator(smsCode string) (FinalizeResult, error)

FinalizeAddAuthenticator does pretty much what it says once you've sucessfully called this method you need to save the instance of `SteamGuardAccount` stored in `LinkedAccount` or you risk losing access to your steam account

type CaptchaGID

type CaptchaGID string

CaptchaGID can be returned as a string, or an integeral -1, constancy is awsome

func (*CaptchaGID) String

func (c *CaptchaGID) String() string

func (*CaptchaGID) URL

func (c *CaptchaGID) URL() string

URL returns a fully qualified URL (string) poiting to the captcha image

func (*CaptchaGID) UnmarshalJSON

func (c *CaptchaGID) UnmarshalJSON(b []byte) error

type Confirmation

type Confirmation struct {
	ConfirmationID          string
	ConfirmationKey         string
	ConfirmationDescription string
}

Confirmation storage

type FinalizeAuthenticatorResponse

type FinalizeAuthenticatorResponse struct {
	Response struct {
		Status     int       `json:"status"`
		ServerTime timestamp `json:"server_time"`
		WantMore   bool      `json:"want_more"`
		Success    bool      `json:"success"`
	} `json:"response"`
}

type FinalizeResult

type FinalizeResult int
const (
	BadSMSCode FinalizeResult = iota // Bad code was given
	UnableToGenerateCorrectCodes
	Success
	FinalizeGeneralFailure
)

func (FinalizeResult) String

func (f FinalizeResult) String() string

type HasPhoneResponse

type HasPhoneResponse struct {
	HasPhone bool `json:"has_phone"`
}

type LinkResult

type LinkResult int
const (
	MustProvidePhoneNumber LinkResult = iota // No phone number on the account
	MustRemovePhoneNumber                    // A phone number is already on the account
	AwaitingFinalization                     // Must provide an SMS code
	LinkGeneralFailure                       // General failure (really now!)
)

func (LinkResult) String

func (l LinkResult) String() string

type LoginResponse

type LoginResponse struct {
	Success         bool       `json:"success"`
	LoginComplete   bool       `json:"login_complete"`
	OAuth           *OAuth     `json:"oauth"`
	CaptchaNeeded   bool       `json:"captcha_needed"`
	CaptchaGID      CaptchaGID `json:"captcha_gid"`
	SteamID         SteamID    `json:"emailsteamid"`
	EmailAuthNeeded bool       `json:"emailauth_needed"`
	TwoFactorNeeded bool       `json:"requires_twofactor"`
	Message         string     `json:"message"`
}

LoginResponse represents the response sent from Steam servers.

type LoginResult

type LoginResult int

LoginResult is the type of login result. Should probably be replaced with a bunch of errors?

const (
	LoginOkay LoginResult = iota
	LoginGeneralFailure
	BadRSA
	BadCredentials
	NeedCaptcha
	Need2FA
	NeedEmail
)

Various LoginResults. You can call .String() to get a human representation. LoginGeneralFailure is more protocol level and usually has an err also.

func (LoginResult) String

func (l LoginResult) String() string

type OAuth

type OAuth struct {
	SteamID          SteamID `json:"steamid"`
	OAuthToken       string  `json:"oauth_token"`
	SteamLogin       string  `json:"wgtoken"`
	SteamLoginSecure string  `json:"wgtoken_secure"`
	Webcookie        string  `json:"webcookie"`
}

OAuth represents the embedded oauth object sent in the LoginResponse. This is actually sent as a string JSON blob but you don't have to deal with that, it's all handled for you.

func (*OAuth) UnmarshalJSON

func (o *OAuth) UnmarshalJSON(b []byte) (err error)

type RemoveAuthenticatorResponse

type RemoveAuthenticatorResponse struct {
	Response struct {
		Success bool `json:"success"`
	} `json:"response"`
}

RemoveAuthenticatorResponse contains the response to the request to remove the authenticator

type SendConfirmationResponse

type SendConfirmationResponse struct {
	Success bool `json:"success"`
}

SendConfirmationResponse contains the response to confirmation requests

type SessionData

type SessionData struct {
	SessionID        string
	SteamLogin       string
	SteamLoginSecure string
	WebCookie        string
	OAuthToken       string
	SteamID          SteamID
}

func (*SessionData) SetCookies

func (s *SessionData) SetCookies(jar http.CookieJar)

type SteamGuardAccount

type SteamGuardAccount struct {
	SharedSecret   string       `json:"shared_secret"`
	SerialNumber   string       `json:"serial_number"`
	RevocationCode string       `json:"revocation_code"`
	URI            string       `json:"uri"`
	ServerTime     timestamp    `json:"server_time"`
	AccountName    string       `json:"account_name"`
	TokenGID       string       `json:"token_gid"`
	IdentitySecret string       `json:"identity_secret"`
	Secret1        string       `json:"secret_1"`
	Status         int          `json:"status"`
	DeviceID       string       `json:"device_id"`
	FullyEnrolled  bool         `json:"fully_enrolled"`
	Session        *SessionData `json:"session"`
}

SteamGuardAccount is a structure to represent an authenticated account, you need to save/export this data or you risk losing access to your account

func (*SteamGuardAccount) AcceptConfirmation

func (s *SteamGuardAccount) AcceptConfirmation(conf *Confirmation) bool

func (*SteamGuardAccount) DeactivateAuthenticator

func (s *SteamGuardAccount) DeactivateAuthenticator() bool

DeactivateAuthenticator will disable steamguard for this authenticator

func (*SteamGuardAccount) Export

func (s *SteamGuardAccount) Export() (string, error)

Export the account data as a json string

func (*SteamGuardAccount) FetchConfirmations

func (s *SteamGuardAccount) FetchConfirmations() []*Confirmation

func (*SteamGuardAccount) GenerateSteamGuardCode

func (s *SteamGuardAccount) GenerateSteamGuardCode() string

GenerateSteamGuardCode for the this account at this time

func (*SteamGuardAccount) GenerateSteamGuardCodeForTime

func (s *SteamGuardAccount) GenerateSteamGuardCodeForTime(atTime time.Time) string

GenerateSteamGuardCodeForTime for the given time

func (*SteamGuardAccount) Import

func (s *SteamGuardAccount) Import(jsonStr string) error

Import account data from a json string

func (*SteamGuardAccount) Load

func (s *SteamGuardAccount) Load(r io.Reader) error

Load account data from an io.Reader json string

func (*SteamGuardAccount) RejectConfirmation

func (s *SteamGuardAccount) RejectConfirmation(conf *Confirmation) bool

func (*SteamGuardAccount) Save

func (s *SteamGuardAccount) Save(w io.Writer) error

Save account data to an io.Writer as a json string

type SteamID

type SteamID uint64

SteamID is usually returned and used as a string, this just insures consistant handling

func (*SteamID) MarshalJSON

func (s *SteamID) MarshalJSON() ([]byte, error)

func (*SteamID) String

func (s *SteamID) String() string

func (*SteamID) UnmarshalJSON

func (s *SteamID) UnmarshalJSON(b []byte) error

type UserLogin

type UserLogin struct {
	Username string
	Password string
	SteamID  SteamID

	RequiresCaptcha bool
	CaptchaGID      CaptchaGID
	CaptchaText     string

	RequiresEmail bool
	EmailDomain   string
	EmailCode     string

	Requires2FA   bool
	TwoFactorCode string

	Session  *SessionData
	LoggedIn bool
	// contains filtered or unexported fields
}

UserLogin lets you log in to steam as a user. Once you provide it with a username and a password you are free to try to DoLogin().

This can be used on it's own without SteamGuardAccount provided you have the ability to access your email and parse the tokens

func NewUserLogin

func NewUserLogin(username, password string) *UserLogin

NewUserLogin allocates and returns a new UserLogin.

func (*UserLogin) CaptchaURL

func (u *UserLogin) CaptchaURL() string

CaptchaURL returns a fully qualified URL to a given captcha GID

func (*UserLogin) DoLogin

func (u *UserLogin) DoLogin() (LoginResult, error)

DoLogin actually attempt to login. Creates a fresh session if required. Grabs the RSA public key. Encrypts your password. Attempts to authenticate.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL