Some manipulations of the token to allow the reuse of a refresh token if available.
This commit is contained in:
parent
b838c8e2cb
commit
59a549c298
1 changed files with 119 additions and 133 deletions
238
main.go
238
main.go
|
@ -3,7 +3,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -16,10 +18,8 @@ import (
|
||||||
skillsclient "client/skills"
|
skillsclient "client/skills"
|
||||||
|
|
||||||
httptransport "github.com/go-openapi/runtime/client"
|
httptransport "github.com/go-openapi/runtime/client"
|
||||||
|
//"database/sql"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
"database/sql"
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Character struct {
|
type Character struct {
|
||||||
|
@ -28,11 +28,6 @@ type Character struct {
|
||||||
ExpiresOn string
|
ExpiresOn string
|
||||||
}
|
}
|
||||||
|
|
||||||
const htmlIndex = `<html><body>
|
|
||||||
<a href="/login">Log in</a>
|
|
||||||
</body></html>
|
|
||||||
`
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
googleOauthConfig = &oauth2.Config{
|
googleOauthConfig = &oauth2.Config{
|
||||||
RedirectURL: "http://localhost:3000/callback",
|
RedirectURL: "http://localhost:3000/callback",
|
||||||
|
@ -51,106 +46,87 @@ var (
|
||||||
oauthStateString = "random"
|
oauthStateString = "random"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ctx = context.Background()
|
||||||
|
var messages = make(chan *oauth2.Token)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
cToken := getDatabaseToken()
|
||||||
|
|
||||||
db, err := sql.Open("sqlite3", "./foo.db")
|
if cToken == nil {
|
||||||
if err != nil {
|
cToken = getNewAuthorizationToken()
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
_, _ = db.Exec("CREATE TABLE IF NOT EXISTS properties (id integer NOT NULL PRIMARY KEY, name TEXT);")
|
|
||||||
|
|
||||||
tx, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
stmt, err := tx.Prepare("insert into foo(id, name) values(?, ?)")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
_, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.Commit()
|
|
||||||
|
|
||||||
rows, err := db.Query("select id, name from foo")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
for rows.Next() {
|
|
||||||
var id int
|
|
||||||
var name string
|
|
||||||
err = rows.Scan(&id, &name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(id, name)
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, err = db.Prepare("select name from foo where id = ?")
|
client := googleOauthConfig.Client(oauth2.NoContext, cToken)
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
var name string
|
|
||||||
err = stmt.QueryRow("3").Scan(&name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(name)
|
|
||||||
|
|
||||||
_, err = db.Exec("delete from foo")
|
m := getCharacterInfo(client)
|
||||||
if err != nil {
|
fmt.Printf("Character id is %d\n", m.CharacterID)
|
||||||
log.Fatal(err)
|
|
||||||
|
getCharacterSkillQueue(client, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Exec("insert into foo(id, name) values(1, 'foo'), (2, 'bar'), (3, 'baz')")
|
func getCharacterInfo(client *http.Client) *Character {
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
req, _ := http.NewRequest("GET", "https://login.eveonline.com/oauth/verify", nil)
|
||||||
|
response, errDo := client.Do(req)
|
||||||
|
if errDo != nil {
|
||||||
|
fmt.Printf("Request error '%s'\n", errDo)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err = db.Query("select id, name from foo")
|
defer response.Body.Close()
|
||||||
if err != nil {
|
contents, _ := ioutil.ReadAll(response.Body)
|
||||||
log.Fatal(err)
|
|
||||||
}
|
var m Character
|
||||||
defer rows.Close()
|
errJson := json.Unmarshal(contents, &m)
|
||||||
for rows.Next() {
|
if errJson != nil {
|
||||||
var id int
|
fmt.Printf("JSON read error with '%s'\n", errJson)
|
||||||
var name string
|
return nil
|
||||||
err = rows.Scan(&id, &name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(id, name)
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Name: %s\n", m.CharacterName)
|
||||||
|
fmt.Printf("Id: %d\n", m.CharacterID)
|
||||||
|
|
||||||
http.HandleFunc("/", handleMain)
|
return &m
|
||||||
http.HandleFunc("/login", handleGoogleLogin)
|
|
||||||
http.HandleFunc("/callback", handleGoogleCallback)
|
|
||||||
fmt.Println(http.ListenAndServe(":3000", nil))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMain(w http.ResponseWriter, r *http.Request) {
|
func getCharacterSkillQueue(client *http.Client, m *Character) {
|
||||||
fmt.Fprintf(w, htmlIndex)
|
|
||||||
|
// create the transport
|
||||||
|
transport := httptransport.NewWithClient("esi.tech.ccp.is", "/latest", []string{"https"}, client)
|
||||||
|
|
||||||
|
// create the API client, with the transport
|
||||||
|
swaggerclient := apiclient.New(transport, strfmt.Default)
|
||||||
|
|
||||||
|
charIDSkilqueue := skillsclient.NewGetCharactersCharacterIDSkillqueueParams().WithCharacterID(m.CharacterID)
|
||||||
|
skillqueueresp, _ := swaggerclient.Skills.GetCharactersCharacterIDSkillqueue(charIDSkilqueue, nil)
|
||||||
|
|
||||||
|
skillqueue := skillqueueresp.Payload
|
||||||
|
|
||||||
|
for _, skill := range skillqueue {
|
||||||
|
// element is the element from someSlice for where we are
|
||||||
|
name := "UNK"
|
||||||
|
level := skill.FinishedLevel
|
||||||
|
id := skill.SkillID
|
||||||
|
startDate := skill.StartDate
|
||||||
|
endDate := skill.FinishDate
|
||||||
|
|
||||||
|
fmt.Printf(" %s: %d\n %d - %s to %s\n\n", name, id, level, startDate, endDate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
func getNewAuthorizationToken() *oauth2.Token {
|
||||||
url := googleOauthConfig.AuthCodeURL(oauthStateString)
|
http.HandleFunc("/", handleLogin)
|
||||||
|
http.HandleFunc("/callback", handleAuthenticationCallback)
|
||||||
|
go func() {
|
||||||
|
log.Println("No available token. Please visit http://localhost:3000 to renew.")
|
||||||
|
http.ListenAndServe(":3000", nil)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return <-messages
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
url := googleOauthConfig.AuthCodeURL(oauthStateString, oauth2.AccessTypeOffline)
|
||||||
|
|
||||||
// https://eveonline-third-party-documentation.readthedocs.io/en/latest/sso/authentication.html
|
// https://eveonline-third-party-documentation.readthedocs.io/en/latest/sso/authentication.html
|
||||||
// response_type: Must be set to “code”.
|
// response_type: Must be set to “code”.
|
||||||
|
@ -159,29 +135,27 @@ func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
func handleAuthenticationCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
state := r.FormValue("state")
|
state := r.FormValue("state")
|
||||||
if state != oauthStateString {
|
if state != oauthStateString {
|
||||||
fmt.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
|
log.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
|
||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
// No token to pass, we will get one on the second pass
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
code := r.FormValue("code")
|
code := r.FormValue("code")
|
||||||
token, err := googleOauthConfig.Exchange(oauth2.NoContext, code)
|
token, err := googleOauthConfig.Exchange(oauth2.NoContext, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Code exchange failed with '%s'\n", err)
|
log.Printf("Code exchange failed with '%s'\n", err)
|
||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
// No token to pass, we will get one on the second pass
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Println("Access token: " + token.AccessToken)
|
client := googleOauthConfig.Client(oauth2.NoContext, token)
|
||||||
//fmt.Println("Refresh token: " + token.RefreshToken)
|
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "https://login.eveonline.com/oauth/verify", nil)
|
req, err := http.NewRequest("GET", "https://login.eveonline.com/oauth/verify", nil)
|
||||||
req.Header.Add("Authorization", "Bearer "+token.AccessToken)
|
|
||||||
response, _ := client.Do(req)
|
response, _ := client.Do(req)
|
||||||
|
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
|
@ -195,31 +169,43 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, "Name: %s\n", m.CharacterName)
|
fmt.Fprintf(w, "Got token for character %s.\n", m.CharacterName)
|
||||||
fmt.Fprintf(w, "Id: %d\n", m.CharacterID)
|
fmt.Fprintf(w, "You can now close this navigator tab.\n")
|
||||||
fmt.Fprintf(w, "Token: %s\n\n", token.AccessToken)
|
|
||||||
|
|
||||||
bearerToken := httptransport.BearerToken(token.AccessToken)
|
messages <- token
|
||||||
|
|
||||||
// create the transport
|
|
||||||
transport := httptransport.New("esi.tech.ccp.is", "/latest", []string{"https"})
|
|
||||||
|
|
||||||
// create the API client, with the transport
|
|
||||||
swaggerclient := apiclient.New(transport, strfmt.Default)
|
|
||||||
|
|
||||||
charIDSkilqueue := skillsclient.NewGetCharactersCharacterIDSkillqueueParams().WithCharacterID(m.CharacterID)
|
|
||||||
skillqueueresp, _ := swaggerclient.Skills.GetCharactersCharacterIDSkillqueue(charIDSkilqueue, bearerToken)
|
|
||||||
|
|
||||||
skillqueue := skillqueueresp.Payload
|
|
||||||
|
|
||||||
for _, skill := range skillqueue {
|
|
||||||
// element is the element from someSlice for where we are
|
|
||||||
name := "UNK"
|
|
||||||
level := skill.FinishedLevel
|
|
||||||
id := skill.SkillID
|
|
||||||
startDate := skill.StartDate
|
|
||||||
endDate := skill.FinishDate
|
|
||||||
|
|
||||||
fmt.Fprintf(w, "%s: %d\n %d - %s to %s\n\n", name, id, level, startDate, endDate)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDatabaseToken() *oauth2.Token {
|
||||||
|
/*
|
||||||
|
db, err := sql.Open("sqlite3", "./foo.db")
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
_, err = db.Exec("CREATE TABLE IF NOT EXISTS properties (id text NOT NULL PRIMARY KEY, value TEXT);")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := db.Prepare("SELECT value FROM properties WHERE id = ?")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer stmt.Close()
|
||||||
|
var refreshToken string
|
||||||
|
|
||||||
|
err = stmt.QueryRow("refreshToken").Scan(&refreshToken)
|
||||||
|
if err != nil {
|
||||||
|
refreshToken = ""
|
||||||
|
}
|
||||||
|
fmt.Println("Found token :" + refreshToken)
|
||||||
|
|
||||||
|
return refreshToken
|
||||||
|
*/
|
||||||
|
log.Print("Using hardcoded refresh token")
|
||||||
|
|
||||||
|
token := new(oauth2.Token)
|
||||||
|
token.RefreshToken = "RZVPAbQpDq4qjwGwWNEHRssnfIEiD789B9nWWyZAZXcuQ2FhulkokZt21uNuRe7D0"
|
||||||
|
token.TokenType = "Bearer"
|
||||||
|
|
||||||
|
return token
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue