mirror of
https://github.com/github/codeql.git
synced 2025-12-20 18:56:32 +01:00
311 lines
8.2 KiB
Go
311 lines
8.2 KiB
Go
package main
|
|
|
|
//go:generate depstubber -vendor golang.org/x/oauth2 Config,Endpoint
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
func main() {}
|
|
|
|
const stateStringConst = "state"
|
|
|
|
var stateStringVar = "state"
|
|
|
|
func badWithStringLiteralState(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL("state") // BAD
|
|
_ = url
|
|
// ...
|
|
}
|
|
func badWithConstState(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // BAD
|
|
_ = url
|
|
// ...
|
|
}
|
|
func badWithFixedVarState(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringVar) // BAD
|
|
_ = url
|
|
// ...
|
|
}
|
|
func badWithFixedStateReturned(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
state := newFixedState()
|
|
url := conf.AuthCodeURL(state) // BAD
|
|
_ = url
|
|
// ...
|
|
}
|
|
func newFixedState() string {
|
|
return "state"
|
|
}
|
|
|
|
func betterWithVariableStateReturned(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
state := generateStateOauthCookie(w)
|
|
url := conf.AuthCodeURL(state) // OK, because the state is not a constant.
|
|
_ = url
|
|
// ...
|
|
}
|
|
func generateStateOauthCookie(w http.ResponseWriter) string {
|
|
b := make([]byte, 128)
|
|
rand.Read(b)
|
|
state := base64.URLEncoding.EncodeToString(b)
|
|
// TODO: save the state string to cookies or HTML storage.
|
|
return state
|
|
}
|
|
func okWithMixedVarState(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
state := fmt.Sprintf("%s-%s", stateStringVar, NewCSRFToken())
|
|
|
|
url := conf.AuthCodeURL(state) // OK, because the state is not a constant.
|
|
_ = url
|
|
// ...
|
|
}
|
|
|
|
func NewCSRFToken() string {
|
|
b := make([]byte, 128)
|
|
rand.Read(b)
|
|
randomToken := base64.URLEncoding.EncodeToString(b)
|
|
return randomToken
|
|
}
|
|
func okWithConstStatePrinter(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal.
|
|
fmt.Printf("Visit the URL for the auth dialog: %v", url)
|
|
// ...
|
|
|
|
var code string
|
|
if _, err := fmt.Scan(&code); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
_ = code
|
|
// ...
|
|
}
|
|
func okWithConstStateFPrinter(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal.
|
|
fmt.Printf("Visit the URL for the auth dialog: %v", url)
|
|
// ...
|
|
|
|
var code string
|
|
if _, err := fmt.Fscan(os.Stdin, &code); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
_ = code
|
|
// ...
|
|
}
|
|
func okWithConstStateBufio(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal.
|
|
fmt.Printf("Visit the URL for the auth dialog: %v", url)
|
|
// ...
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
_ = scanner
|
|
// ...
|
|
}
|
|
func okWithConstStateLogger(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal.
|
|
log.Printf("Visit the URL for the auth dialog: %v", url)
|
|
// ...
|
|
|
|
var code string
|
|
if _, err := fmt.Fscan(os.Stdin, &code); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
_ = code
|
|
// ...
|
|
}
|
|
func badWithConstStatePrinter(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // BAD
|
|
fmt.Printf("LOG: URL %v", url)
|
|
// ...
|
|
}
|
|
|
|
func okWithLocalUrl(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
RedirectURL: "http://localhost:8080",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a local url
|
|
_ = url
|
|
}
|
|
|
|
func okWithLocalUrlSprintf(w http.ResponseWriter) {
|
|
port := 8080
|
|
conf := &oauth2.Config{
|
|
RedirectURL: fmt.Sprintf("%s:%d", "http://localhost:8080", port),
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a local url
|
|
_ = url
|
|
}
|
|
|
|
func okWithOutOfBoundsToken(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
RedirectURL: "oob",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a token indicating out-of-band communication
|
|
_ = url
|
|
}
|
|
|
|
func tryGetState(success bool) (string, string, int, error) {
|
|
if success {
|
|
return NewCSRFToken(), "dummy", 0, nil
|
|
} else {
|
|
return "", "", 0, errors.New("success not set")
|
|
}
|
|
}
|
|
|
|
func okConstantOnlySuppliedAlongsideError(w http.ResponseWriter) {
|
|
conf := &oauth2.Config{
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Scopes: []string{"SCOPE1", "SCOPE2"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://provider.com/o/oauth2/auth",
|
|
TokenURL: "https://provider.com/o/oauth2/token",
|
|
},
|
|
}
|
|
|
|
token, _, _, err := tryGetState(len(os.Args)%3 == 1)
|
|
if err != nil {
|
|
url := conf.AuthCodeURL(token) // OK because constant states coming from tryGetState only occur with errors
|
|
_ = url
|
|
}
|
|
}
|