github.com/twilio/twilio-go@v1.20.1/client/jwt/access_token_test.go (about)

     1  package jwt
     2  
     3  import (
     4  	"os"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  var AccountSid string
    13  var SigningKeySid string
    14  var Params AccessTokenParams
    15  
    16  func TestMain(m *testing.M) {
    17  	AccountSid = "AC123"
    18  	SigningKeySid = "SK123"
    19  	Params = AccessTokenParams{
    20  		AccountSid:    AccountSid,
    21  		SigningKeySid: SigningKeySid,
    22  		Secret:        "secret",
    23  	}
    24  	ret := m.Run()
    25  	os.Exit(ret)
    26  }
    27  
    28  func validateClaims(t *testing.T, payload map[string]interface{}) {
    29  	assert.Equal(t, SigningKeySid, payload["iss"])
    30  	assert.Equal(t, AccountSid, payload["sub"])
    31  	assert.NotZero(t, payload["jti"])
    32  	assert.NotZero(t, payload["exp"])
    33  	assert.NotNil(t, payload["grants"])
    34  	now := float64(time.Now().Unix())
    35  	assert.Greater(t, payload["exp"].(float64), now)
    36  	assert.True(t, strings.Contains(payload["jti"].(string), payload["iss"].(string)))
    37  }
    38  
    39  func testInit(t *testing.T) *AccessToken {
    40  	accessToken := CreateAccessToken(Params)
    41  	token, err := accessToken.ToJwt()
    42  	assert.Nil(t, err)
    43  	assert.NotNil(t, token)
    44  
    45  	decodedToken, err := accessToken.FromJwt(token, "secret")
    46  	assert.Nil(t, err)
    47  	assert.NotNil(t, decodedToken)
    48  	return decodedToken
    49  }
    50  
    51  func assertPanic(t *testing.T, f func(grant BaseGrant)) {
    52  	defer func() {
    53  		if r := recover(); r == nil {
    54  			t.Errorf("The code did not panic")
    55  		}
    56  	}()
    57  	f(nil)
    58  }
    59  
    60  func TestAccessTokenSimple(t *testing.T) {
    61  	params := Params
    62  	params.Identity = "identity"
    63  	params.Nbf = 3600
    64  	accessToken := CreateAccessToken(params)
    65  
    66  	token, err := accessToken.ToJwt()
    67  	assert.Nil(t, err)
    68  	assert.NotNil(t, token)
    69  
    70  	decodedToken, err := accessToken.FromJwt(token, "secret")
    71  	assert.Nil(t, err)
    72  	assert.NotNil(t, decodedToken)
    73  	assert.Equal(t, "secret", decodedToken.baseJwt.SecretKey)
    74  	validateClaims(t, decodedToken.Payload())
    75  }
    76  
    77  func TestAccessTokenWithNoValidation(t *testing.T) {
    78  	accessToken := CreateAccessToken(Params)
    79  	token, err := accessToken.ToJwt()
    80  	assert.Nil(t, err)
    81  	assert.NotNil(t, token)
    82  
    83  	decodedToken, err := accessToken.FromJwt(token, "")
    84  	assert.Nil(t, err)
    85  	assert.NotNil(t, decodedToken)
    86  	assert.Equal(t, "", decodedToken.baseJwt.SecretKey)
    87  	validateClaims(t, decodedToken.Payload())
    88  }
    89  
    90  func TestAccessTokenWithoutSecret(t *testing.T) {
    91  	params := Params
    92  	params.Secret = ""
    93  	accessToken := CreateAccessToken(params)
    94  	defer func() {
    95  		if r := recover(); r == nil {
    96  			t.Errorf("The code did not panic")
    97  		}
    98  	}()
    99  	_, _ = accessToken.ToJwt()
   100  }
   101  
   102  func TestAccessTokenHeaders(t *testing.T) {
   103  	params := Params
   104  	params.Identity = "identity"
   105  	params.Region = "US"
   106  	params.Nbf = 0
   107  	params.Ttl = 50
   108  	params.ValidUntil = 0
   109  	accessToken := CreateAccessToken(params)
   110  
   111  	token, err := accessToken.ToJwt()
   112  	assert.Nil(t, err)
   113  	assert.NotNil(t, token)
   114  
   115  	decodedToken, err := accessToken.FromJwt(token, "secret")
   116  	assert.Nil(t, err)
   117  	assert.NotNil(t, decodedToken)
   118  	assert.Equal(t, "secret", decodedToken.baseJwt.SecretKey)
   119  
   120  	headers := decodedToken.Headers()
   121  
   122  	assert.Equal(t, "US", headers["twr"])
   123  	assert.Equal(t, "HS256", headers["alg"])
   124  	assert.Equal(t, "twilio-fpa;v=1", headers["cty"])
   125  	assert.Equal(t, "JWT", headers["typ"])
   126  }
   127  
   128  func TestParams(t *testing.T) {
   129  	now := float64(time.Now().Unix())
   130  	params := Params
   131  	params.Identity = "identity"
   132  	params.Region = "US"
   133  	params.Nbf = now
   134  	params.Ttl = 7200
   135  	params.ValidUntil = now + 10800
   136  	accessToken := CreateAccessToken(params)
   137  	token, err := accessToken.ToJwt()
   138  	assert.Nil(t, err)
   139  	assert.NotNil(t, token)
   140  
   141  	decodedToken, err := accessToken.FromJwt(token, "secret")
   142  	assert.Nil(t, err)
   143  	assert.NotNil(t, decodedToken)
   144  	payload := decodedToken.Payload()
   145  	assert.Equal(t, now, payload["nbf"])
   146  	assert.Equal(t, now+10800, payload["exp"])
   147  }
   148  
   149  func TestAccessTokenPayload(t *testing.T) {
   150  	now := float64(time.Now().Unix())
   151  	params := Params
   152  	params.Identity = "identity"
   153  	params.Region = "US"
   154  	params.Nbf = 360
   155  	params.Ttl = 50
   156  	params.ValidUntil = 200 + now
   157  	accessToken := CreateAccessToken(params)
   158  	token, err := accessToken.ToJwt()
   159  	assert.Nil(t, err)
   160  	assert.NotNil(t, token)
   161  
   162  	decodedToken, err := accessToken.FromJwt(token, "secret")
   163  	assert.Nil(t, err)
   164  	assert.NotNil(t, decodedToken)
   165  	assert.Equal(t, "secret", decodedToken.baseJwt.SecretKey)
   166  	assert.Equal(t, "US", decodedToken.Region)
   167  	assert.Equal(t, "identity", decodedToken.Identity)
   168  	assert.Equal(t, AccountSid, decodedToken.AccountSid)
   169  	assert.Equal(t, SigningKeySid, decodedToken.SigningKeySid)
   170  
   171  	payload := decodedToken.Payload()
   172  	assert.Equal(t, "SK123", payload["iss"])
   173  	assert.Equal(t, float64(360), payload["nbf"])
   174  	assert.Equal(t, "AC123", payload["sub"])
   175  	assert.True(t, strings.Contains(payload["jti"].(string), payload["iss"].(string)))
   176  	assert.Len(t, decodedToken.Grants, 0)
   177  }
   178  
   179  func TestHeaders(t *testing.T) {
   180  	decodedToken := testInit(t)
   181  	headers := decodedToken.Headers()
   182  	assert.Equal(t, "HS256", headers["alg"])
   183  	assert.Equal(t, "twilio-fpa;v=1", headers["cty"])
   184  	assert.Equal(t, "JWT", headers["typ"])
   185  }
   186  
   187  func TestChatGrant(t *testing.T) {
   188  	params := Params
   189  	params.Identity = "identity"
   190  	params.Region = "US"
   191  	params.Nbf = 3600
   192  	accessToken := CreateAccessToken(params)
   193  
   194  	accessToken.AddGrant(&ChatGrant{
   195  		ServiceSid:        "IS123",
   196  		EndpointID:        "Endpoint123",
   197  		DeploymentRoleSid: "Role123",
   198  		PushCredentialSid: "CR123",
   199  	})
   200  
   201  	token, err := accessToken.ToJwt()
   202  	assert.Nil(t, err)
   203  	assert.NotNil(t, token)
   204  
   205  	decodedToken, err := accessToken.FromJwt(token, "secret")
   206  	assert.Nil(t, err)
   207  	assert.NotNil(t, decodedToken)
   208  	assert.Len(t, decodedToken.Grants, 1)
   209  	payload := decodedToken.Payload()
   210  	// identity should exist in the grants map as well
   211  	assert.Len(t, payload["grants"], 2)
   212  
   213  	chatGrantDecoded := payload["grants"].(map[string]interface{})["chat"].(map[string]interface{})
   214  	assert.NotNil(t, chatGrantDecoded)
   215  	assert.Equal(t, "Role123", chatGrantDecoded["deployment_role_sid"])
   216  	assert.Equal(t, "Endpoint123", chatGrantDecoded["endpoint_id"])
   217  	assert.Equal(t, "CR123", chatGrantDecoded["push_credential_sid"])
   218  	assert.Equal(t, "IS123", chatGrantDecoded["service_sid"])
   219  }
   220  
   221  func TestConversationsGrant(t *testing.T) {
   222  	accessToken := CreateAccessToken(Params)
   223  	accessToken.AddGrant(&ConversationsGrant{ConfigurationProfileSid: "CP123"})
   224  
   225  	token, err := accessToken.ToJwt()
   226  	assert.Nil(t, err)
   227  	assert.NotNil(t, token)
   228  
   229  	decodedToken, err := accessToken.FromJwt(token, "secret")
   230  	assert.Nil(t, err)
   231  	assert.NotNil(t, decodedToken)
   232  	payload := decodedToken.Payload()
   233  	assert.Len(t, decodedToken.Grants, 1)
   234  	assert.Len(t, payload["grants"], 1)
   235  
   236  	conversationsGrantDecoded := payload["grants"].(map[string]interface{})["rtc"].(map[string]interface{})
   237  	assert.NotNil(t, conversationsGrantDecoded)
   238  	assert.Equal(t, "CP123", conversationsGrantDecoded["configuration_profile_sid"])
   239  }
   240  
   241  func TestIpMessagingGrant(t *testing.T) {
   242  	accessToken := CreateAccessToken(Params)
   243  	accessToken.AddGrant(&IpMessagingGrant{
   244  		ServiceSid:        "IS123",
   245  		EndpointID:        "Endpoint123",
   246  		DeploymentRoleSid: "Role123",
   247  		PushCredentialSid: "CR123",
   248  	})
   249  
   250  	token, err := accessToken.ToJwt()
   251  	assert.Nil(t, err)
   252  	assert.NotNil(t, token)
   253  
   254  	decodedToken, err := accessToken.FromJwt(token, "secret")
   255  	assert.Nil(t, err)
   256  	assert.NotNil(t, decodedToken)
   257  	assert.Len(t, decodedToken.Grants, 1)
   258  	payload := decodedToken.Payload()
   259  	assert.Len(t, payload["grants"], 1)
   260  
   261  	ipMessagingGrantDecoded := payload["grants"].(map[string]interface{})["ip_messaging"].(map[string]interface{})
   262  	assert.NotNil(t, ipMessagingGrantDecoded)
   263  	assert.Equal(t, "IS123", ipMessagingGrantDecoded["service_sid"])
   264  	assert.Equal(t, "Endpoint123", ipMessagingGrantDecoded["endpoint_id"])
   265  	assert.Equal(t, "Role123", ipMessagingGrantDecoded["deployment_role_sid"])
   266  	assert.Equal(t, "CR123", ipMessagingGrantDecoded["push_credential_sid"])
   267  }
   268  
   269  func TestSyncGrant(t *testing.T) {
   270  	accessToken := CreateAccessToken(Params)
   271  	accessToken.AddGrant(&SyncGrant{
   272  		ServiceSid: "IS123",
   273  		EndpointID: "Endpoint123",
   274  	})
   275  
   276  	token, err := accessToken.ToJwt()
   277  	assert.Nil(t, err)
   278  	assert.NotNil(t, token)
   279  
   280  	decodedToken, err := accessToken.FromJwt(token, "secret")
   281  	assert.Nil(t, err)
   282  	assert.NotNil(t, decodedToken)
   283  	assert.Len(t, decodedToken.Grants, 1)
   284  	payload := decodedToken.Payload()
   285  	assert.Len(t, payload["grants"], 1)
   286  
   287  	syncGrantDecoded := payload["grants"].(map[string]interface{})["data_sync"].(map[string]interface{})
   288  	assert.NotNil(t, syncGrantDecoded)
   289  	assert.Equal(t, "IS123", syncGrantDecoded["service_sid"])
   290  	assert.Equal(t, "Endpoint123", syncGrantDecoded["endpoint_id"])
   291  }
   292  
   293  func TestVideoGrant(t *testing.T) {
   294  	accessToken := CreateAccessToken(Params)
   295  	accessToken.AddGrant(&VideoGrant{Room: "RM123"})
   296  
   297  	token, err := accessToken.ToJwt()
   298  	assert.Nil(t, err)
   299  	assert.NotNil(t, token)
   300  
   301  	decodedToken, err := accessToken.FromJwt(token, "secret")
   302  	assert.Nil(t, err)
   303  	assert.NotNil(t, decodedToken)
   304  	assert.Len(t, decodedToken.Grants, 1)
   305  	payload := decodedToken.Payload()
   306  	assert.Len(t, payload["grants"], 1)
   307  
   308  	videoGrantDecoded := payload["grants"].(map[string]interface{})["video"].(map[string]interface{})
   309  	assert.NotNil(t, videoGrantDecoded)
   310  	assert.Equal(t, "RM123", videoGrantDecoded["room"])
   311  }
   312  
   313  func TestVoiceGrant(t *testing.T) {
   314  	accessToken := CreateAccessToken(Params)
   315  	accessToken.AddGrant(&VoiceGrant{
   316  		Incoming: Incoming{Allow: true},
   317  		Outgoing: Outgoing{
   318  			ApplicationSid: "SID123",
   319  			ApplicationParams: map[string]interface{}{
   320  				"foo": "bar",
   321  			},
   322  		},
   323  		PushCredentialSid: "Push123",
   324  		EndpointID:        "Endpoint123",
   325  	})
   326  
   327  	token, err := accessToken.ToJwt()
   328  	assert.Nil(t, err)
   329  	assert.NotNil(t, token)
   330  
   331  	decodedToken, err := accessToken.FromJwt(token, "secret")
   332  	assert.Nil(t, err)
   333  	assert.NotNil(t, decodedToken)
   334  	assert.Len(t, decodedToken.Grants, 1)
   335  	payload := decodedToken.Payload()
   336  	assert.Len(t, payload["grants"], 1)
   337  
   338  	voiceGrantDecoded := payload["grants"].(map[string]interface{})["voice"].(map[string]interface{})
   339  	assert.NotNil(t, voiceGrantDecoded)
   340  	assert.Equal(t, "Endpoint123", voiceGrantDecoded["endpoint_id"])
   341  	assert.Equal(t, "Push123", voiceGrantDecoded["push_credential_sid"])
   342  
   343  	incoming := voiceGrantDecoded["incoming"].(map[string]interface{})
   344  	assert.Equal(t, true, incoming["allow"])
   345  	outgoing := voiceGrantDecoded["outgoing"].(map[string]interface{})
   346  	assert.Equal(t, "SID123", outgoing["application_sid"])
   347  	assert.Equal(t, "bar", outgoing["params"].(map[string]interface{})["foo"])
   348  }
   349  
   350  func TestTaskRouterGrant(t *testing.T) {
   351  	accessToken := CreateAccessToken(Params)
   352  	accessToken.AddGrant(&TaskRouterGrant{
   353  		WorkspaceSid: "WS123",
   354  		WorkerSid:    "WK123",
   355  		Role:         "worker",
   356  	})
   357  
   358  	token, err := accessToken.ToJwt()
   359  	assert.Nil(t, err)
   360  	assert.NotNil(t, token)
   361  
   362  	decodedToken, err := accessToken.FromJwt(token, "secret")
   363  	assert.Nil(t, err)
   364  	assert.NotNil(t, decodedToken)
   365  	payload := decodedToken.Payload()
   366  	assert.Len(t, payload["grants"], 1)
   367  
   368  	taskRouterGrantDecoded := payload["grants"].(map[string]interface{})["task_router"].(map[string]interface{})
   369  	assert.NotNil(t, taskRouterGrantDecoded)
   370  	assert.Equal(t, "WS123", taskRouterGrantDecoded["workspace_sid"])
   371  	assert.Equal(t, "WK123", taskRouterGrantDecoded["worker_sid"])
   372  	assert.Equal(t, "worker", taskRouterGrantDecoded["role"])
   373  }
   374  
   375  func TestPlaybackGrant(t *testing.T) {
   376  	accessToken := CreateAccessToken(Params)
   377  	accessToken.AddGrant(&PlaybackGrant{
   378  		"requestCredentials": nil,
   379  		"playbackUrl":        "https://000.us-east-1.playback.live-video.net/api/video/v1/us-east-000.channel.000?token=xxxxx",
   380  		"playerStreamerSid":  "VJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
   381  	})
   382  
   383  	token, err := accessToken.ToJwt()
   384  	assert.Nil(t, err)
   385  	assert.NotNil(t, token)
   386  
   387  	decodedToken, err := accessToken.FromJwt(token, "secret")
   388  	assert.Nil(t, err)
   389  	assert.NotNil(t, decodedToken)
   390  	assert.Len(t, decodedToken.Grants, 1)
   391  	payload := decodedToken.Payload()
   392  	assert.Len(t, payload["grants"], 1)
   393  
   394  	playbackGrantDecoded := payload["grants"].(map[string]interface{})["player"].(map[string]interface{})
   395  	assert.NotNil(t, playbackGrantDecoded)
   396  	assert.Equal(t, nil, playbackGrantDecoded["requestCredentials"])
   397  	assert.Equal(t, "https://000.us-east-1.playback.live-video.net/api/video/v1/us-east-000.channel.000?token=xxxxx", playbackGrantDecoded["playbackUrl"])
   398  	assert.Equal(t, "VJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", playbackGrantDecoded["playerStreamerSid"])
   399  }
   400  
   401  func TestMultipleGrants(t *testing.T) {
   402  	accessToken := CreateAccessToken(Params)
   403  	accessToken.AddGrant(&TaskRouterGrant{
   404  		WorkspaceSid: "WS123",
   405  		WorkerSid:    "WK123",
   406  		Role:         "worker",
   407  	})
   408  
   409  	accessToken.AddGrant(&SyncGrant{})
   410  
   411  	token, err := accessToken.ToJwt()
   412  	assert.Nil(t, err)
   413  	assert.NotNil(t, token)
   414  
   415  	decodedToken, err := accessToken.FromJwt(token, "secret")
   416  	assert.Nil(t, err)
   417  	assert.NotNil(t, decodedToken)
   418  	payload := decodedToken.Payload()
   419  	assert.Len(t, payload["grants"], 2)
   420  
   421  	taskRouterGrantDecoded := payload["grants"].(map[string]interface{})["task_router"].(map[string]interface{})
   422  	assert.NotNil(t, taskRouterGrantDecoded)
   423  	assert.Equal(t, "WS123", taskRouterGrantDecoded["workspace_sid"])
   424  	assert.Equal(t, "WK123", taskRouterGrantDecoded["worker_sid"])
   425  	assert.Equal(t, "worker", taskRouterGrantDecoded["role"])
   426  
   427  	syncGrantDecoded := payload["grants"].(map[string]interface{})["data_sync"].(map[string]interface{})
   428  	assert.NotNil(t, syncGrantDecoded)
   429  }
   430  
   431  func TestGrantsDuringInit(t *testing.T) {
   432  	grants := []BaseGrant{
   433  		&VideoGrant{Room: "room"},
   434  		&VoiceGrant{},
   435  	}
   436  	params := Params
   437  	params.Grants = grants
   438  	accessToken := CreateAccessToken(params)
   439  	token, err := accessToken.ToJwt()
   440  	assert.Nil(t, err)
   441  	assert.NotNil(t, token)
   442  
   443  	decodedToken, err := accessToken.FromJwt(token, "secret")
   444  	assert.Nil(t, err)
   445  	assert.NotNil(t, decodedToken)
   446  
   447  	payload := decodedToken.Payload()
   448  	assert.Len(t, payload["grants"], 2)
   449  
   450  	videoGrantDecoded := payload["grants"].(map[string]interface{})["video"].(map[string]interface{})
   451  	assert.NotNil(t, videoGrantDecoded)
   452  	assert.Equal(t, "room", videoGrantDecoded["room"])
   453  
   454  	voiceGrantDecoded := payload["grants"].(map[string]interface{})["voice"].(map[string]interface{})
   455  	assert.NotNil(t, voiceGrantDecoded)
   456  }
   457  
   458  func TestValidateGrant(t *testing.T) {
   459  	accessToken := CreateAccessToken(Params)
   460  	assertPanic(t, accessToken.AddGrant)
   461  }
   462  
   463  func TestGrantsToString(t *testing.T) {
   464  	chatGrant := &ChatGrant{}
   465  	assert.True(t, strings.HasPrefix(chatGrant.ToString(), "<ChatGrant"))
   466  
   467  	conversationsGrant := &ConversationsGrant{}
   468  	assert.True(t, strings.HasPrefix(conversationsGrant.ToString(), "<ConversationsGrant"))
   469  
   470  	ipMessagingGrant := &IpMessagingGrant{}
   471  	assert.True(t, strings.HasPrefix(ipMessagingGrant.ToString(), "<IpMessagingGrant"))
   472  
   473  	syncGrant := &SyncGrant{}
   474  	assert.True(t, strings.HasPrefix(syncGrant.ToString(), "<SyncGrant"))
   475  
   476  	voiceGrant := &VoiceGrant{}
   477  	assert.True(t, strings.HasPrefix(voiceGrant.ToString(), "<VoiceGrant"))
   478  
   479  	videoGrant := &VideoGrant{}
   480  	assert.True(t, strings.HasPrefix(videoGrant.ToString(), "<VideoGrant"))
   481  
   482  	playbackGrant := &PlaybackGrant{}
   483  	assert.True(t, strings.HasPrefix(playbackGrant.ToString(), "<PlaybackGrant"))
   484  }