Some manipulations of the token to allow the reuse of a refresh token if available.

This commit is contained in:
Thomas Schwery 2017-01-29 14:38:41 +01:00
parent b838c8e2cb
commit 59a549c298

252
main.go
View file

@ -3,7 +3,9 @@ package main
import (
"encoding/json"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"io/ioutil"
"net/http"
@ -16,10 +18,8 @@ import (
skillsclient "client/skills"
httptransport "github.com/go-openapi/runtime/client"
"database/sql"
_ "github.com/mattn/go-sqlite3"
//"database/sql"
//_ "github.com/mattn/go-sqlite3"
)
type Character struct {
@ -28,11 +28,6 @@ type Character struct {
ExpiresOn string
}
const htmlIndex = `<html><body>
<a href="/login">Log in</a>
</body></html>
`
var (
googleOauthConfig = &oauth2.Config{
RedirectURL: "http://localhost:3000/callback",
@ -51,106 +46,87 @@ var (
oauthStateString = "random"
)
var ctx = context.Background()
var messages = make(chan *oauth2.Token)
func main() {
cToken := getDatabaseToken()
db, err := sql.Open("sqlite3", "./foo.db")
if err != nil {
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)
if cToken == nil {
cToken = getNewAuthorizationToken()
}
stmt, err = db.Prepare("select name from foo where id = ?")
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)
client := googleOauthConfig.Client(oauth2.NoContext, cToken)
_, err = db.Exec("delete from foo")
if err != nil {
log.Fatal(err)
}
m := getCharacterInfo(client)
fmt.Printf("Character id is %d\n", m.CharacterID)
_, err = db.Exec("insert into foo(id, name) values(1, 'foo'), (2, 'bar'), (3, 'baz')")
if err != nil {
log.Fatal(err)
}
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)
}
http.HandleFunc("/", handleMain)
http.HandleFunc("/login", handleGoogleLogin)
http.HandleFunc("/callback", handleGoogleCallback)
fmt.Println(http.ListenAndServe(":3000", nil))
getCharacterSkillQueue(client, m)
}
func handleMain(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, htmlIndex)
func getCharacterInfo(client *http.Client) *Character {
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
}
defer response.Body.Close()
contents, _ := ioutil.ReadAll(response.Body)
var m Character
errJson := json.Unmarshal(contents, &m)
if errJson != nil {
fmt.Printf("JSON read error with '%s'\n", errJson)
return nil
}
fmt.Printf("Name: %s\n", m.CharacterName)
fmt.Printf("Id: %d\n", m.CharacterID)
return &m
}
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
url := googleOauthConfig.AuthCodeURL(oauthStateString)
func getCharacterSkillQueue(client *http.Client, m *Character) {
// 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 getNewAuthorizationToken() *oauth2.Token {
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
// 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)
}
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
func handleAuthenticationCallback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
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)
// No token to pass, we will get one on the second pass
return
}
code := r.FormValue("code")
token, err := googleOauthConfig.Exchange(oauth2.NoContext, code)
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)
// No token to pass, we will get one on the second pass
return
}
//fmt.Println("Access token: " + token.AccessToken)
//fmt.Println("Refresh token: " + token.RefreshToken)
client := &http.Client{}
client := googleOauthConfig.Client(oauth2.NoContext, token)
req, err := http.NewRequest("GET", "https://login.eveonline.com/oauth/verify", nil)
req.Header.Add("Authorization", "Bearer "+token.AccessToken)
response, _ := client.Do(req)
defer response.Body.Close()
@ -195,31 +169,43 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
return
}
fmt.Fprintf(w, "Name: %s\n", m.CharacterName)
fmt.Fprintf(w, "Id: %d\n", m.CharacterID)
fmt.Fprintf(w, "Token: %s\n\n", token.AccessToken)
fmt.Fprintf(w, "Got token for character %s.\n", m.CharacterName)
fmt.Fprintf(w, "You can now close this navigator tab.\n")
bearerToken := httptransport.BearerToken(token.AccessToken)
// 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)
}
messages <- token
}
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
}