diff --git a/go.mod b/go.mod index b47439442..1ea0bb3b4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/markbates/goth -go 1.18 +go 1.23.0 + +toolchain go1.23.6 require ( github.com/go-chi/chi/v5 v5.1.0 @@ -13,15 +15,16 @@ require ( github.com/markbates/going v1.0.0 github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c github.com/stretchr/testify v1.9.0 - golang.org/x/oauth2 v0.17.0 + golang.org/x/oauth2 v0.27.0 ) require ( cloud.google.com/go/compute v1.20.1 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/compute/metadata v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/securecookie v1.1.1 // indirect @@ -34,6 +37,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect golang.org/x/crypto v0.21.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.32.0 // indirect diff --git a/go.sum b/go.sum index 40b2e0765..4449261c8 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZN cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -13,6 +15,8 @@ github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -68,6 +72,7 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -91,6 +96,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/providers/instagram/instagram.go b/providers/instagram/instagram.go index b4703dc44..dcdcb317b 100644 --- a/providers/instagram/instagram.go +++ b/providers/instagram/instagram.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "net/http" "net/url" @@ -19,7 +20,7 @@ import ( var ( authURL = "https://api.instagram.com/oauth/authorize/" tokenURL = "https://api.instagram.com/oauth/access_token" - endPointProfile = "https://api.instagram.com/v1/users/self/" + endPointProfile = "https://graph.instagram.com/me" ) // New creates a new Instagram provider, and sets up important connection details. @@ -76,24 +77,28 @@ func (p *Provider) BeginAuth(state string) (goth.Session, error) { // FetchUser will go to Instagram and access basic information about the user. func (p *Provider) FetchUser(session goth.Session) (goth.User, error) { sess := session.(*Session) + user := goth.User{ AccessToken: sess.AccessToken, Provider: p.Name(), } if user.AccessToken == "" { - // data is not yet retrieved since accessToken is still empty + log.Printf("[Instagram] Error: Missing access token for provider %s", p.Name()) return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName) } - response, err := p.Client().Get(endPointProfile + "?access_token=" + url.QueryEscape(sess.AccessToken)) + requestURL := endPointProfile + "?fields=id,username,account_type,media_count,profile_picture_url&access_token=" + url.QueryEscape(sess.AccessToken) + response, err := p.Client().Get(requestURL) if err != nil { + log.Printf("[Instagram] Error making request: %v", err) return user, err } defer response.Body.Close() if response.StatusCode != http.StatusOK { + log.Printf("[Instagram] Received non-200 status code: %d", response.StatusCode) return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, response.StatusCode) } @@ -101,39 +106,45 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) { if err != nil { return user, err } + err = json.NewDecoder(bytes.NewReader(bits)).Decode(&user.RawData) if err != nil { return user, err } + err = userFromReader(bytes.NewReader(bits), &user) - return user, err + if err != nil { + return user, err + } else { + return user, nil + } } func userFromReader(reader io.Reader, user *goth.User) error { u := struct { - Data struct { - ID string `json:"id"` - UserName string `json:"username"` - FullName string `json:"full_name"` - ProfilePicture string `json:"profile_picture"` - Bio string `json:"bio"` - Website string `json:"website"` - Counts struct { - Media int `json:"media"` - Follows int `json:"follows"` - FollowedBy int `json:"followed_by"` - } `json:"counts"` - } `json:"data"` + ID string `json:"id"` + UserName string `json:"username"` + AccountType string `json:"account_type"` + MediaCount int64 `json:"media_count"` + Biography string `json:"biography"` + ProfileUrl string `json:"profile_picture_url"` + Name string `json:"name"` + + // Add other fields as needed }{} err := json.NewDecoder(reader).Decode(&u) if err != nil { + log.Printf("[Instagram] Error decoding user data: %v", err) return err } - user.UserID = u.Data.ID - user.Name = u.Data.FullName - user.NickName = u.Data.UserName - user.AvatarURL = u.Data.ProfilePicture - user.Description = u.Data.Bio + user.UserID = u.ID + user.NickName = u.UserName + user.Description = u.Biography + user.AvatarURL = u.ProfileUrl + user.Name = u.Name + user.AccountType = u.AccountType + + // Set other fields as needed return err } @@ -147,11 +158,11 @@ func newConfig(p *Provider, scopes []string) *oauth2.Config { TokenURL: tokenURL, }, Scopes: []string{ - "basic", + "instagram_business_basic", }, } defaultScopes := map[string]struct{}{ - "basic": {}, + "instagram_business_basic": {}, } for _, scope := range scopes { @@ -159,7 +170,6 @@ func newConfig(p *Provider, scopes []string) *oauth2.Config { c.Scopes = append(c.Scopes, scope) } } - return c } diff --git a/user.go b/user.go index 3a8fd6c54..c6389d410 100644 --- a/user.go +++ b/user.go @@ -28,4 +28,5 @@ type User struct { RefreshToken string ExpiresAt time.Time IDToken string + AccountType string }