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 }