github.com/clerkinc/clerk-sdk-go@v1.49.1/clerk/middleware_test.go (about)

     1  package clerk
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/go-jose/go-jose/v3"
    12  	"github.com/go-jose/go-jose/v3/jwt"
    13  )
    14  
    15  func TestWithSession_addSessionToContext(t *testing.T) {
    16  	apiToken := "apiToken"
    17  	sessionId := "someSessionId"
    18  	sessionToken := "someSessionToken"
    19  
    20  	client, mux, serverUrl, teardown := setup(apiToken)
    21  	defer teardown()
    22  
    23  	expectedResponse := dummySessionJson
    24  
    25  	mux.HandleFunc("/sessions/"+sessionId+"/verify", func(w http.ResponseWriter, req *http.Request) {
    26  		fmt.Fprint(w, expectedResponse)
    27  	})
    28  
    29  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    30  		// this handler should be called after the middleware has added the `ActiveSession`
    31  		activeSession := r.Context().Value(ActiveSession)
    32  		resp, _ := json.Marshal(activeSession)
    33  		fmt.Fprint(w, string(resp))
    34  	})
    35  
    36  	mux.Handle("/session", WithSession(client)(dummyHandler))
    37  
    38  	request := setupRequest(&sessionId, &sessionToken)
    39  	request.URL.Host = serverUrl.Host
    40  	request.URL.Path = "/v1/session"
    41  
    42  	var got Session
    43  	_, _ = client.Do(request, &got)
    44  
    45  	var want Session
    46  	_ = json.Unmarshal([]byte(expectedResponse), &want)
    47  
    48  	if !reflect.DeepEqual(got, want) {
    49  		t.Errorf("Response = %v, want %v", got, want)
    50  	}
    51  }
    52  
    53  func TestWithSession_returnsErrorIfVerificationFails(t *testing.T) {
    54  	apiToken := "apiToken"
    55  	sessionId := "someSessionId"
    56  	sessionToken := "someSessionToken"
    57  
    58  	client, mux, serverUrl, teardown := setup(apiToken)
    59  	defer teardown()
    60  
    61  	mux.HandleFunc("/sessions/"+sessionId+"/verify", func(w http.ResponseWriter, req *http.Request) {
    62  		// return error
    63  		w.WriteHeader(400)
    64  	})
    65  
    66  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    67  		// this handler should be called after the middleware has added the `ActiveSession`
    68  		t.Errorf("This should never be called!")
    69  	})
    70  
    71  	mux.Handle("/session", WithSession(client)(dummyHandler))
    72  
    73  	request := setupRequest(&sessionId, &sessionToken)
    74  	request.URL.Host = serverUrl.Host
    75  	request.URL.Path = "/v1/session"
    76  
    77  	resp, _ := client.Do(request, nil)
    78  
    79  	if resp.StatusCode != http.StatusBadRequest {
    80  		t.Errorf("Was expecting 400 error code, found %v instead", resp.StatusCode)
    81  	}
    82  }
    83  
    84  func TestWithSession_addSessionClaimsToContext_Header(t *testing.T) {
    85  	c, mux, serverUrl, teardown := setup("apiToken")
    86  	defer teardown()
    87  
    88  	expectedClaims := dummySessionClaims
    89  
    90  	token, pubKey := testGenerateTokenJWT(t, expectedClaims, "kid")
    91  
    92  	client := c.(*client)
    93  	client.jwksCache.set(testBuildJWKS(t, pubKey, jose.RS256, "kid"))
    94  
    95  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    96  		// this handler should be called after the middleware has added the `ActiveClaims`
    97  		claims := r.Context().Value(ActiveSessionClaims)
    98  		_ = json.NewEncoder(w).Encode(claims)
    99  	})
   100  
   101  	mux.Handle("/claims", WithSession(c)(dummyHandler))
   102  
   103  	req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/claims", serverUrl), nil)
   104  	req.Header.Set("Authorization", token)
   105  
   106  	resp, err := http.DefaultClient.Do(req)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	defer resp.Body.Close()
   112  
   113  	var got SessionClaims
   114  	_ = json.NewDecoder(resp.Body).Decode(&got)
   115  
   116  	if !reflect.DeepEqual(got, expectedClaims) {
   117  		t.Errorf("Response = %v, want %v", got, expectedClaims)
   118  	}
   119  }
   120  
   121  func TestWithSession_addSessionClaimsToContext_Cookie(t *testing.T) {
   122  	c, mux, serverUrl, teardown := setup("apiToken")
   123  	defer teardown()
   124  
   125  	expectedClaims := dummySessionClaims
   126  
   127  	token, pubKey := testGenerateTokenJWT(t, expectedClaims, "kid")
   128  
   129  	client := c.(*client)
   130  	client.jwksCache.set(testBuildJWKS(t, pubKey, jose.RS256, "kid"))
   131  
   132  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   133  		// this handler should be called after the middleware has added the `ActiveClaims`
   134  		activeClaims := r.Context().Value(ActiveSessionClaims)
   135  		_ = json.NewEncoder(w).Encode(activeClaims)
   136  	})
   137  
   138  	mux.Handle("/claims", WithSession(c)(dummyHandler))
   139  
   140  	req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/claims", serverUrl), nil)
   141  	req.AddCookie(&http.Cookie{
   142  		Name:     "__session",
   143  		Value:    token,
   144  		Secure:   true,
   145  		HttpOnly: true,
   146  	})
   147  
   148  	resp, err := http.DefaultClient.Do(req)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  
   153  	defer resp.Body.Close()
   154  
   155  	var got SessionClaims
   156  	_ = json.NewDecoder(resp.Body).Decode(&got)
   157  
   158  	if !reflect.DeepEqual(got, expectedClaims) {
   159  		t.Errorf("Response = %v, want %v", got, expectedClaims)
   160  	}
   161  }
   162  
   163  func TestWithSession_returnsErrorIfTokenVerificationFails(t *testing.T) {
   164  	c, mux, serverUrl, teardown := setup("apiToken")
   165  	defer teardown()
   166  
   167  	expectedClaims := dummySessionClaims
   168  	expectedClaims.Expiry = jwt.NewNumericDate(time.Now().Add(time.Second * -1))
   169  
   170  	token, pubKey := testGenerateTokenJWT(t, expectedClaims, "kid")
   171  
   172  	client := c.(*client)
   173  	client.jwksCache.set(testBuildJWKS(t, pubKey, jose.RS256, "kid"))
   174  
   175  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   176  		// this handler should be called after the middleware has added the `ActiveClaims`
   177  		activeClaims := r.Context().Value(ActiveSessionClaims)
   178  		_ = json.NewEncoder(w).Encode(activeClaims)
   179  	})
   180  
   181  	mux.Handle("/claims", WithSession(c)(dummyHandler))
   182  
   183  	req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/claims", serverUrl), nil)
   184  	req.Header.Set("Authorization", token)
   185  
   186  	resp, _ := http.DefaultClient.Do(req)
   187  
   188  	if resp.StatusCode != http.StatusUnauthorized {
   189  		t.Errorf("Was expecting 401 error code, found %v instead", resp.StatusCode)
   190  	}
   191  }
   192  
   193  func TestWithSession_returnsErrorIfTokenMissing(t *testing.T) {
   194  	apiToken := "apiToken"
   195  
   196  	c, mux, serverUrl, teardown := setup(apiToken)
   197  	defer teardown()
   198  
   199  	dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   200  		// this handler should be called after the middleware has added the `ActiveSession`
   201  		t.Errorf("This should never be called!")
   202  	})
   203  
   204  	mux.Handle("/claims", WithSession(c)(dummyHandler))
   205  
   206  	req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/claims", serverUrl), nil)
   207  
   208  	resp, _ := http.DefaultClient.Do(req)
   209  
   210  	if resp.StatusCode != http.StatusBadRequest {
   211  		t.Errorf("Was expecting 400 error code, found %v instead", resp.StatusCode)
   212  	}
   213  }