alpha
Login
or
Join now
andri.dk
/
gostack
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
[READ-ONLY] Mirror of https://github.com/andrioid/gostack. Experimental backend stack (work-in-progress)
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
can now verify firebase id token
author
Andri Óskarsson
date
8 years ago
(Jan 28, 2018, 9:29 AM +0100)
commit
8586d43d
8586d43d81bc22469d5ec6b590abfa5bdd216c3a
parent
9e2269ec
9e2269eceaa17a4b8215dd54208482e50e8c9a69
+68
-34
2 changed files
Expand all
Collapse all
Unified
Split
cmd
serve.go
graphql
graphql.go
+15
-6
cmd/serve.go
View file
Reviewed
···
1
1
package cmd
2
2
3
3
import (
4
4
+
"context"
4
5
"fmt"
6
6
+
"log"
5
7
"net/http"
6
8
"os"
7
9
10
10
+
firebase "firebase.google.com/go"
8
11
"github.com/andrioid/gostack/graphql"
9
12
"github.com/andrioid/gostack/module"
10
13
"github.com/andrioid/gostack/places"
···
13
16
_ "github.com/jinzhu/gorm/dialects/sqlite"
14
17
"github.com/spf13/cobra"
15
18
"github.com/spf13/viper"
19
19
+
"google.golang.org/api/option"
16
20
)
17
21
18
22
// serveCmd represents the serve command
···
61
65
// Firebase
62
66
// https://firebase.google.com/docs/auth/admin/verify-id-tokens
63
67
// https://firebase.google.com/docs/admin/setup
64
64
-
//opt := option.WithCredentialsFile(viper.GetString("firebase.serviceAccountFile"))
65
65
-
//app, err := firebase.NewApp(context.Background(), nil, opt)
66
66
-
//if err != nil {
67
67
-
// log.Fatalf("error initializing app: %v\n", err)
68
68
-
//}
68
68
+
opt := option.WithCredentialsFile(viper.GetString("firebase.serviceAccountFile"))
69
69
+
app, err := firebase.NewApp(context.Background(), nil, opt)
70
70
+
if err != nil {
71
71
+
log.Fatalf("error initializing app: %v\n", err)
72
72
+
}
73
73
+
firebaseAuth, err := app.Auth(context.Background())
74
74
+
if err != nil {
75
75
+
panic(err)
76
76
+
}
69
77
// TODO: app isn't accessable to graphql package, so maybe create middleware for token verification
70
78
71
79
// Modules
···
75
83
graphql.CreateSchema(modules)
76
84
77
85
r := mux.NewRouter()
78
78
-
r.HandleFunc("/graphql", graphql.HTTPHandler)
86
86
+
87
87
+
r.HandleFunc("/graphql", graphql.HTTPHandler(firebaseAuth))
79
88
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./client/build")))
80
89
http.Handle("/", r)
81
90
+53
-28
graphql/graphql.go
View file
Reviewed
···
5
5
"fmt"
6
6
"net/http"
7
7
8
8
+
"firebase.google.com/go/auth"
8
9
"github.com/andrioid/gostack/module"
9
10
"github.com/graphql-go/graphql"
10
11
)
12
12
+
13
13
+
const bearer = "Bearer"
11
14
12
15
// https://github.com/graphql-go/graphql/blob/master/examples/http/main.go
13
16
···
51
54
var schema graphql.Schema
52
55
53
56
// HTTPHandler tells the http-server how to process GraphQL
54
54
-
func HTTPHandler(w http.ResponseWriter, r *http.Request) {
55
55
-
var query string
56
56
-
auth := r.Header.Get("Authorization")
57
57
+
func HTTPHandler(a *auth.Client) func(http.ResponseWriter, *http.Request) {
58
58
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59
59
+
var query string
60
60
+
t, _ := authorizationFromHeader(r)
57
61
58
58
-
if auth != "" {
59
59
-
// TODO: Verify the token found with Firebase SDK
60
60
-
fmt.Println("Auth header", auth)
61
61
-
}
62
62
-
if r.Method == http.MethodPost {
63
63
-
decoder := json.NewDecoder(r.Body)
64
64
-
var t struct {
65
65
-
Query string
62
62
+
token, err := a.VerifyIDToken(t)
63
63
+
if err != nil {
64
64
+
fmt.Println("Error verifying token", err)
65
65
+
}
66
66
+
67
67
+
if t != "" {
68
68
+
// TODO: Verify the token found with Firebase SDK
69
69
+
fmt.Println("Auth header", t, token)
70
70
+
}
71
71
+
if r.Method == http.MethodPost {
72
72
+
decoder := json.NewDecoder(r.Body)
73
73
+
var t struct {
74
74
+
Query string
75
75
+
}
76
76
+
err := decoder.Decode(&t)
77
77
+
if err != nil {
78
78
+
http.Error(w, "Invalid request", http.StatusBadRequest)
79
79
+
return
80
80
+
}
81
81
+
defer r.Body.Close()
82
82
+
query = t.Query
83
83
+
} else {
84
84
+
query = r.URL.Query().Get("query")
66
85
}
67
67
-
err := decoder.Decode(&t)
68
68
-
if err != nil {
69
69
-
http.Error(w, "Invalid request", http.StatusBadRequest)
70
70
-
return
86
86
+
if query == "" {
87
87
+
fmt.Println("Query is empty")
71
88
}
72
72
-
defer r.Body.Close()
73
73
-
query = t.Query
74
74
-
} else {
75
75
-
query = r.URL.Query().Get("query")
89
89
+
result := ExecuteQuery(query, schema)
90
90
+
w.Header().Set("Content-Type", "application/json")
91
91
+
w.Header().Set("Access-Control-Allow-Credentials", "true")
92
92
+
w.Header().Set("Access-Control-Allow-Methods", "POST")
93
93
+
w.Header().Set("Access-Control-Allow-Headers", "ContentType, Authorization")
94
94
+
w.Header().Set("Access-Control-Allow-Origin", "*")
95
95
+
json.NewEncoder(w).Encode(result)
96
96
+
return
97
97
+
})
98
98
+
}
99
99
+
100
100
+
func authorizationFromHeader(req *http.Request) (string, error) {
101
101
+
header := req.Header.Get("Authorization")
102
102
+
if header == "" {
103
103
+
return "", fmt.Errorf("Authorization header not found")
76
104
}
77
77
-
if query == "" {
78
78
-
fmt.Println("Query is empty")
105
105
+
106
106
+
l := len(bearer)
107
107
+
if len(header) > l+1 && header[:l] == bearer {
108
108
+
return header[l+1:], nil
79
109
}
80
80
-
result := ExecuteQuery(query, schema)
81
81
-
w.Header().Set("Content-Type", "application/json")
82
82
-
w.Header().Set("Access-Control-Allow-Credentials", "true")
83
83
-
w.Header().Set("Access-Control-Allow-Methods", "POST")
84
84
-
w.Header().Set("Access-Control-Allow-Headers", "ContentType, Authorization")
85
85
-
w.Header().Set("Access-Control-Allow-Origin", "*")
86
86
-
json.NewEncoder(w).Encode(result)
110
110
+
111
111
+
return "", fmt.Errorf("Authorization header format must be 'Bearer {token}'")
87
112
}
88
113
89
114
// ExecuteQuery does stuff