Skip to content

Commit

Permalink
feat: add client credentials test
Browse files Browse the repository at this point in the history
  • Loading branch information
TristanSpeakEasy committed Feb 22, 2024
1 parent 1562840 commit df2455e
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"

"github.com/speakeasy-api/speakeasy-api-test-service/internal/acceptHeaders"
"github.com/speakeasy-api/speakeasy-api-test-service/internal/clientcredentials"
"github.com/speakeasy-api/speakeasy-api-test-service/internal/errors"
"github.com/speakeasy-api/speakeasy-api-test-service/internal/eventstreams"
"github.com/speakeasy-api/speakeasy-api-test-service/internal/pagination"
Expand Down Expand Up @@ -47,6 +48,8 @@ func main() {
r.HandleFunc("/eventstreams/rich", eventstreams.HandleEventStreamRich).Methods(http.MethodPost)
r.HandleFunc("/eventstreams/chat", eventstreams.HandleEventStreamChat).Methods(http.MethodPost)
r.HandleFunc("/eventstreams/differentdataschemas", eventstreams.HandleEventStreamDifferentDataSchemas).Methods(http.MethodPost)
r.HandleFunc("/clientcredentials/token", clientcredentials.HandleTokenRequest).Methods(http.MethodPost)
r.HandleFunc("/clientcredentials/authenticatedrequest", clientcredentials.HandleAuthenticatedRequest).Methods(http.MethodPost)

bind := ":8080"
if bindArg != nil {
Expand Down
96 changes: 96 additions & 0 deletions internal/clientcredentials/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package clientcredentials

import (
"encoding/json"
"net/http"
"slices"
"strings"
"sync"
)

var state = sync.Map{}

const (
firstAccessToken = "super-duper-access-token"
secondAccessToken = "second-super-duper-access-token"
)

func HandleTokenRequest(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
http.Error(w, "invalid_request", http.StatusBadRequest)
return
}

grant_type := r.Form.Get("grant_type")
if grant_type != "client_credentials" {
http.Error(w, "invalid_grant", http.StatusBadRequest)
return
}

clientID := r.Form.Get("client_id")
clientSecret := r.Form.Get("client_secret")
if clientID == "" || clientSecret == "" {
http.Error(w, "invalid_request", http.StatusBadRequest)
return
}
if clientID != "speakeasy-sdks" || !strings.HasPrefix(clientSecret, "supersecret-") {
http.Error(w, "invalid_client", http.StatusUnauthorized)
return
}

scopes := strings.Split(r.Form.Get("scope"), " ")
if len(scopes) == 0 {
http.Error(w, "invalid_scope", http.StatusBadRequest)
return
}

if !slices.Contains(scopes, "read") || !slices.Contains(scopes, "write") {
http.Error(w, "invalid_scope", http.StatusBadRequest)
return
}

accessToken := firstAccessToken

_, ok := state.Load(clientSecret)
if !ok {
state.Store(clientSecret, true)
} else {
accessToken = secondAccessToken
}

w.Header().Set("Content-Type", "application/json")

type tokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
}

response := tokenResponse{
AccessToken: accessToken,
TokenType: "Bearer",
ExpiresIn: 0,
}

if err := json.NewEncoder(w).Encode(response); err != nil {
http.Error(w, "server_error", http.StatusInternalServerError)
return
}
}

func HandleAuthenticatedRequest(w http.ResponseWriter, r *http.Request) {
accessToken := r.Header.Get("Authorization")
if accessToken == "" {
http.Error(w, "invalid_request", http.StatusBadRequest)
return
}

accessToken = strings.TrimPrefix(accessToken, "Bearer ")
if accessToken != firstAccessToken && accessToken != secondAccessToken {
http.Error(w, "invalid_token", http.StatusUnauthorized)
return
}

w.WriteHeader(http.StatusOK)
}

0 comments on commit df2455e

Please sign in to comment.