Skip to content

Commit 5508e02

Browse files
authored
Merge pull request #92 from twitchdev/feature/auth-improvements-#80-#82
Feature/auth improvements #80 #82
2 parents d7e134b + 6101c72 commit 5508e02

File tree

11 files changed

+198
-32
lines changed

11 files changed

+198
-32
lines changed

internal/mock_api/endpoints/bits/cheermotes.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ func getCheermotes(w http.ResponseWriter, r *http.Request) {
128128
cheermoteBody = append(cheermoteBody, cheermote)
129129
}
130130

131-
resposne, _ := json.Marshal(cheermoteBody)
132-
w.Write(resposne)
131+
response, _ := json.Marshal(cheermoteBody)
132+
w.Write(response)
133133
}
134134

135135
func generateCheermoteImageSizes(prefix string, theme string, imageType string, bits int) CheermoteImageSizes {

internal/mock_api/endpoints/clips/clips.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,21 @@ func getClips(w http.ResponseWriter, r *http.Request) {
9292
}
9393

9494
clips := dbr.Data.([]database.Clip)
95-
apiResposne := models.APIResponse{
95+
apiResponse := models.APIResponse{
9696
Data: clips,
9797
}
9898

99-
if len(apiResposne.Data.([]database.Clip)) == 0 {
100-
apiResposne.Data = []string{}
99+
if len(apiResponse.Data.([]database.Clip)) == 0 {
100+
apiResponse.Data = []string{}
101101
}
102102

103103
if dbr.Limit == len(dbr.Data.([]database.Clip)) {
104-
apiResposne.Pagination = &models.APIPagination{
104+
apiResponse.Pagination = &models.APIPagination{
105105
Cursor: dbr.Cursor,
106106
}
107107
}
108108

109-
bytes, _ := json.Marshal(apiResposne)
109+
bytes, _ := json.Marshal(apiResponse)
110110
w.Write(bytes)
111111
}
112112

internal/mock_api/endpoints/polls/polls.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,17 @@ func getPolls(w http.ResponseWriter, r *http.Request) {
110110
polls = append(polls, dbr.Data.([]database.Poll)...)
111111
}
112112

113-
apiResposne := models.APIResponse{
113+
apiResponse := models.APIResponse{
114114
Data: polls,
115115
}
116116

117117
if dbr != nil && dbr.Cursor != "" {
118-
apiResposne.Pagination = &models.APIPagination{
118+
apiResponse.Pagination = &models.APIPagination{
119119
Cursor: dbr.Cursor,
120120
}
121121
}
122122

123-
bytes, _ := json.Marshal(apiResposne)
123+
bytes, _ := json.Marshal(apiResponse)
124124
w.Write(bytes)
125125
}
126126

@@ -231,16 +231,16 @@ func patchPolls(w http.ResponseWriter, r *http.Request) {
231231
return
232232
}
233233

234-
apiResposne := models.APIResponse{
234+
apiResponse := models.APIResponse{
235235
Data: dbr.Data,
236236
}
237237

238238
if dbr.Cursor != "" {
239-
apiResposne.Pagination = &models.APIPagination{
239+
apiResponse.Pagination = &models.APIPagination{
240240
Cursor: dbr.Cursor,
241241
}
242242
}
243243

244-
bytes, _ := json.Marshal(apiResposne)
244+
bytes, _ := json.Marshal(apiResponse)
245245
w.Write(bytes)
246246
}

internal/mock_api/endpoints/predictions/predictions.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,17 @@ func getPredictions(w http.ResponseWriter, r *http.Request) {
110110
predictions = append(predictions, dbr.Data.([]database.Prediction)...)
111111
}
112112

113-
apiResposne := models.APIResponse{
113+
apiResponse := models.APIResponse{
114114
Data: predictions,
115115
}
116116

117117
if dbr != nil && dbr.Cursor != "" {
118-
apiResposne.Pagination = &models.APIPagination{
118+
apiResponse.Pagination = &models.APIPagination{
119119
Cursor: dbr.Cursor,
120120
}
121121
}
122122

123-
bytes, _ := json.Marshal(apiResposne)
123+
bytes, _ := json.Marshal(apiResponse)
124124
w.Write(bytes)
125125
}
126126

internal/mock_api/endpoints/streams/streamkey.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var streamKeyScopesByMethod = map[string][]string{
3232

3333
type StreamKey struct{}
3434

35-
type StreamKeyResposne struct {
35+
type StreamKeyResponse struct {
3636
StreamKey string `json:"stream_key"`
3737
}
3838

@@ -66,7 +66,7 @@ func getStreamKey(w http.ResponseWriter, r *http.Request) {
6666
return
6767
}
6868

69-
streamKeys := []StreamKeyResposne{{StreamKey: fmt.Sprintf("live_%v_%v", userCtx.UserID, util.RandomGUID())}}
69+
streamKeys := []StreamKeyResponse{{StreamKey: fmt.Sprintf("live_%v_%v", userCtx.UserID, util.RandomGUID())}}
7070

7171
bytes, _ := json.Marshal(models.APIResponse{Data: streamKeys})
7272
w.Write(bytes)

internal/mock_api/endpoints/teams/channel_teams.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var channelTeamsScopesByMethod = map[string][]string{
2828
}
2929

3030
type ChannelTeams struct{}
31-
type ChannelTeamResposne struct {
31+
type ChannelTeamResponse struct {
3232
ID string `json:"id"`
3333
BackgroundImageUrl *string `json:"background_image_url"`
3434
Banner *string `json:"banner"`
@@ -77,9 +77,9 @@ func getChannelTeams(w http.ResponseWriter, r *http.Request) {
7777
if len(team) == 0 {
7878
dbr.Data = make([]database.Team, 0)
7979
}
80-
response := []ChannelTeamResposne{}
80+
response := []ChannelTeamResponse{}
8181
for _, t := range team {
82-
response = append(response, ChannelTeamResposne{
82+
response = append(response, ChannelTeamResponse{
8383
ID: t.ID,
8484
Info: t.Info,
8585
BackgroundImageUrl: t.BackgroundImageUrl,

internal/mock_auth/app_access_token.go

+41-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ import (
1515

1616
type AppAccessTokenEndpoint struct{}
1717

18-
type AppAccessTokenEndpointResposne struct {
18+
type AppAccessTokenRequestBody struct {
19+
ClientID string `json:"client_id"`
20+
ClientSecret string `json:"client_secret"`
21+
GrantType string `json:"grant_type"`
22+
Scope string `json:"scope"`
23+
}
24+
25+
type AppAccessTokenEndpointResponse struct {
1926
AccessToken string `json:"access_token"`
2027
RefreshToken string `json:"refresh_token"`
2128
ExpiresIn int `json:"expires_in"`
@@ -33,12 +40,37 @@ func (e AppAccessTokenEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request
3340
return
3441
}
3542

36-
clientID := r.URL.Query().Get("client_id")
37-
clientSecret := r.URL.Query().Get("client_secret")
38-
grantType := r.URL.Query().Get("grant_type")
39-
scope := r.URL.Query().Get("scope")
40-
scopes := strings.Split(scope, " ")
41-
if clientID == "" || clientSecret == "" || grantType != "client_credentials" {
43+
params := AppAccessTokenRequestBody{
44+
ClientID: r.URL.Query().Get("client_id"),
45+
ClientSecret: r.URL.Query().Get("client_secret"),
46+
GrantType: r.URL.Query().Get("grant_type"),
47+
Scope: r.URL.Query().Get("scope"),
48+
}
49+
50+
if r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
51+
err := r.ParseForm()
52+
if err != nil {
53+
mock_errors.WriteServerError(w, err.Error())
54+
return
55+
}
56+
57+
if r.Form.Get("client_id") != "" {
58+
params.ClientID = r.Form.Get("client_id")
59+
}
60+
if r.Form.Get("client_secret") != "" {
61+
params.ClientSecret = r.Form.Get("client_secret")
62+
}
63+
if r.Form.Get("grant_type") != "" {
64+
params.GrantType = r.Form.Get("grant_type")
65+
}
66+
if r.Form.Get("scope") != "" {
67+
params.Scope = r.Form.Get("scope")
68+
}
69+
}
70+
71+
scopes := strings.Split(params.Scope, " ")
72+
73+
if params.ClientID == "" || params.ClientSecret == "" || params.GrantType != "client_credentials" {
4274
w.WriteHeader(http.StatusBadRequest)
4375
return
4476
}
@@ -55,7 +87,7 @@ func (e AppAccessTokenEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request
5587
return
5688
}
5789

58-
res, err := db.NewQuery(r, 10).GetAuthenticationClient(database.AuthenticationClient{ID: clientID, Secret: clientSecret})
90+
res, err := db.NewQuery(r, 10).GetAuthenticationClient(database.AuthenticationClient{ID: params.ClientID, Secret: params.ClientSecret})
5991
if err != nil {
6092
mock_errors.WriteServerError(w, err.Error())
6193
return
@@ -79,7 +111,7 @@ func (e AppAccessTokenEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request
79111
return
80112
}
81113
ea, _ := time.Parse(time.RFC3339, a.ExpiresAt)
82-
ater := AppAccessTokenEndpointResposne{
114+
ater := AppAccessTokenEndpointResponse{
83115
AccessToken: auth.Token,
84116
RefreshToken: "",
85117
ExpiresIn: int(ea.Sub(time.Now().UTC()).Seconds()),

internal/mock_auth/mock_auth.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ var validScopesByTokenType = map[string]map[string]bool{
5858

5959
func All() []AuthEndpoint {
6060
return []AuthEndpoint{
61-
UserTokenEndpoint{},
6261
AppAccessTokenEndpoint{},
62+
UserTokenEndpoint{},
63+
ValidateTokenEndpoint{},
6364
}
6465
}
6566

internal/mock_auth/mock_auth_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ package mock_auth
44

55
import (
66
"context"
7+
"fmt"
78
"log"
89
"net/http"
910
"net/http/httptest"
11+
"os"
1012
"testing"
13+
"time"
1114

1215
"github.com/stretchr/testify/assert"
1316
"github.com/twitchdev/twitch-cli/internal/database"
@@ -19,6 +22,10 @@ var a *assert.Assertions
1922
var firstRun = true
2023
var ac = database.AuthenticationClient{ID: "222", Secret: "333", Name: "test_client", IsExtension: false}
2124

25+
func TestMain(m *testing.M) {
26+
27+
os.Exit(m.Run())
28+
}
2229
func TestAreValidScopes(t *testing.T) {
2330
a := test_setup.SetupTestEnv(t)
2431

@@ -70,6 +77,46 @@ func TestUserToken(t *testing.T) {
7077
a.Equal(400, resp.StatusCode)
7178
}
7279

80+
func TestValidateToken(t *testing.T) {
81+
a = test_setup.SetupTestEnv(t)
82+
ts := httptest.NewServer(baseMiddleware(ValidateTokenEndpoint{}))
83+
84+
req, _ := http.NewRequest(http.MethodGet, ts.URL+ValidateTokenEndpoint{}.Path(), nil)
85+
resp, err := http.DefaultClient.Do(req)
86+
a.Nil(err, err)
87+
a.Equal(401, resp.StatusCode)
88+
89+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", "auth.Token"))
90+
resp, err = http.DefaultClient.Do(req)
91+
a.Nil(err, err)
92+
a.Equal(401, resp.StatusCode)
93+
94+
db, err := database.NewConnection()
95+
a.Nil(err, err)
96+
defer db.DB.Close()
97+
98+
auth, err := db.NewQuery(nil, 0).CreateAuthorization(database.Authorization{
99+
ClientID: ac.ID,
100+
ExpiresAt: util.GetTimestamp().Add(time.Hour * 4).Format(time.RFC3339),
101+
Scopes: "",
102+
})
103+
104+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", auth.Token))
105+
resp, err = http.DefaultClient.Do(req)
106+
a.Nil(err, err)
107+
a.Equal(200, resp.StatusCode)
108+
109+
auth, err = db.NewQuery(nil, 0).CreateAuthorization(database.Authorization{
110+
ClientID: ac.ID,
111+
ExpiresAt: util.GetTimestamp().Add(time.Hour * 4).Format(time.RFC3339),
112+
Scopes: "user:read:email",
113+
UserID: "1",
114+
})
115+
req.Header.Set("Authorization", fmt.Sprintf("Oauth %v", auth.Token))
116+
resp, err = http.DefaultClient.Do(req)
117+
a.Nil(err, err)
118+
a.Equal(200, resp.StatusCode)
119+
}
73120
func TestAppAccessToken(t *testing.T) {
74121
a = test_setup.SetupTestEnv(t)
75122
ts := httptest.NewServer(baseMiddleware(AppAccessTokenEndpoint{}))
@@ -99,6 +146,7 @@ func TestAppAccessToken(t *testing.T) {
99146
a.Nil(err)
100147
a.Equal(200, resp.StatusCode)
101148
}
149+
102150
func baseMiddleware(next http.Handler) http.Handler {
103151
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
104152
ctx := context.Background()

internal/mock_auth/user_token.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (e UserTokenEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
7777
return
7878
}
7979
ea, _ := time.Parse(time.RFC3339, a.ExpiresAt)
80-
ater := AppAccessTokenEndpointResposne{
80+
ater := AppAccessTokenEndpointResponse{
8181
AccessToken: auth.Token,
8282
RefreshToken: "",
8383
ExpiresIn: int(ea.Sub(time.Now().UTC()).Seconds()),

0 commit comments

Comments
 (0)