diff --git a/Project.toml b/Project.toml index 8cc52d0..2b95553 100644 --- a/Project.toml +++ b/Project.toml @@ -1,14 +1,14 @@ name = "SMARTBackendServices" uuid = "78af60b6-7677-4c75-8291-bd270d1b4390" authors = ["Dilum Aluthge", "contributors"] -version = "1.0.1" +version = "2.0.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" HealthBase = "94e1309d-ccf4-42de-905f-515f1d7b1cae" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -JSONWebTokens = "9b8beb19-0777-58c6-920b-28f749fee4d3" +JWTs = "d850fbd6-035d-5a70-a269-1ca2e636ac6c" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53" URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" @@ -17,14 +17,14 @@ URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" HTTP = "0.9.3" HealthBase = "1.0.1" JSON3 = "1.5.1" -JSONWebTokens = "0.3.4, 1" +JWTs = "0.2.2" TimeZones = "1.5.3" URIs = "1.2" julia = "1.5" [extras] -JSONWebTokens = "9b8beb19-0777-58c6-920b-28f749fee4d3" +MbedTLS = "739be429-bea8-5141-9913-cc70e7f3736d" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["JSONWebTokens", "Test"] +test = ["MbedTLS", "Test"] diff --git a/src/SMARTBackendServices.jl b/src/SMARTBackendServices.jl index 53ed7a8..1dfafca 100644 --- a/src/SMARTBackendServices.jl +++ b/src/SMARTBackendServices.jl @@ -4,7 +4,7 @@ import Dates import HTTP import HealthBase import JSON3 -import JSONWebTokens +import JWTs import Random import TimeZones import URIs diff --git a/src/backend_services.jl b/src/backend_services.jl index 29a641c..5efc9f8 100644 --- a/src/backend_services.jl +++ b/src/backend_services.jl @@ -12,9 +12,18 @@ function _backend_services_create_jwt(config::BackendServicesConfig) "jti" => jti, "exp" => expiration_time_seconds_since_epoch_utc, ) - jwt = JSONWebTokens.encode(config.private_key, jwt_payload_claims_dict) + jwt = JWTs.JWT(; payload = jwt_payload_claims_dict) - return jwt + # Sign + if config.keyid === nothing + JWTs.sign!(jwt, config.key) + else + JWTs.sign!(jwt, config.key, config.keyid) + end + @assert JWTs.issigned(jwt) + @assert config.keyid === nothing || JWTs.kid(jwt) == config.keyid + + return string(jwt) end """ diff --git a/src/jwt.jl b/src/jwt.jl index 4c97c21..1653576 100644 --- a/src/jwt.jl +++ b/src/jwt.jl @@ -1,6 +1,6 @@ function try_decode_jwt(contents::AbstractString) try - jwt_decoded = JSONWebTokens.decode(JSONWebTokens.None(), contents) + jwt_decoded = JWTs.claims(JWTs.JWT(; jwt = contents)) return true, jwt_decoded catch end diff --git a/src/types.jl b/src/types.jl index fe48105..23fb8bb 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,18 +1,20 @@ """ - BackendServicesConfig{PK}(; kwargs...) + BackendServicesConfig{T <: JWTs.JWK}(; kwargs...) ## Required Keyword Arguments: - `iss::String` -- `private_key::PK` +- `key::T` - `sub::String` - `token_endpoint::String` ## Optional Keyword Arguments: - `scope::Union{String, Nothing}`. Default value: `nothing`. +- `keyid::Union{String, Nothing}`. Default value: `nothing`. """ -Base.@kwdef struct BackendServicesConfig{PK <: JSONWebTokens.Encoding} +Base.@kwdef struct BackendServicesConfig{T <: JWTs.JWK} iss::String - private_key::PK + key::T + keyid::Union{String, Nothing} = nothing scope::Union{String, Nothing} = nothing sub::String token_endpoint::String diff --git a/test/basic.jl b/test/basic.jl index c97dfc3..10f42e3 100644 --- a/test/basic.jl +++ b/test/basic.jl @@ -1,11 +1,20 @@ -token_endpoint = "https://launch.smarthealthit.org/v/r4/auth/token" +server = "https://launch.smarthealthit.org/v/r4/" +token_endpoint = server * "auth/token" + +# Signing key +openid_config = String(HTTP.get(server * "fhir/.well-known/openid-configuration").body) +keyset = JWTs.JWKSet(JSON3.read(openid_config)["jwks_uri"]) +JWTs.refresh!(keyset) +keyid, key = first(keyset.keys) +key = JWTs.JWKRSA(key.kind, MbedTLS.parse_keyfile(test_private_key)) client_id = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwdWJfa2V5IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVsSlFrbHFRVTVDWjJ0eGFHdHBSemwzTUVKQlVVVkdRVUZQUTBGUk9FRk5TVWxDUTJkTFEwRlJSVUYzWVdvMVoza3hkRXRvVGtOWVdYTjNOV0YzVkFwd1p5OVRja2xuYm1sU1YybElVVmwyZDFseWFrSk5WSHBYUkhkcGQyRTNXbkZLTDNSalRFTk5lR1Y1T0dRMlRHdDRWbkpoYldOb1lqWkdSMnhaZERaUkNtRnZNbkpRWlRSNGJVZ3hkak4zZW1kbVZqaEljbTFUTTI5R2NqbDRjRFJPTm5rNGNtdFdkekZ2Vmtoc2RqZHpVRTV0VlRkell5OHhhU3RJY1ZOUlRFb0thM3BWY1dOQ2FubzFVME14YkhwMlpYaG5jVzkxWjNKNGRUVk5abWwwTmtGd1pHRjFSVGc0U3k5dVNGVk9TM1l2T1ROWmFqTkNaM3BNSzBGV1UwUkpRUW92Ynpsc2VFVlplVmxHV1RBek5HaFJSVmhwVFVFME4yY3ZVRk5ZU20xU2NHWkRXV2hhVUc4MFNtTkdjRXBoU0V4amVGbGhiRmxVZUdSdVZDODVlREJuQ21sQlJETnJjMlZaY20wNFprd3JjRU5EY1V4bFdHbEZXVm94Y0d0R1pqWjFjMkZ5WVZScVMyeGlaSGxMWjJadEwyNWtWemR5V2xkemJVSkZSVVVyUWtVS01GRkpSRUZSUVVJS0xTMHRMUzFGVGtRZ1VGVkNURWxESUV0RldTMHRMUzB0Q2c9PSIsImlzcyI6Imh0dHBzOi8vd2hhdGV2ZXIuc21hcnQvb3VyLXNhbXBsZS1iYWNrZW5kLXNlcnZpY2UiLCJhY2Nlc3NUb2tlbnNFeHBpcmVJbiI6MSwiaWF0IjoxNTEwNzY2MTQzfQ.7YooXIb64Y3_j38n-Gqwa1PqXc-hz-4xJAJF5oqxJVo" smart_config = BackendServicesConfig(; iss = "https://whatever.smart/our-sample-backend-service", sub = client_id, - private_key = JSONWebTokens.RS384(test_private_key), + key, + keyid, scope = "system/*.*", token_endpoint = token_endpoint, ) diff --git a/test/runtests.jl b/test/runtests.jl index 7372a74..b1605da 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,10 @@ using SMARTBackendServices using Test -import JSONWebTokens +import JSON3 +import JWTs +import HTTP +import MbedTLS include("test_private_key/create.jl")