Created
March 14, 2019 16:19
-
-
Save pr130/07e04cc77efa1c2dff71f17bb39723b6 to your computer and use it in GitHub Desktop.
R functions that allow to check whether named lists are a subset of a bigger list.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# written as part of the sealr package: github.com/jandix/sealr | |
library(purrr) | |
#' | |
#' This function checks that all claims passed in the \code{claims} argument of the jwt function are | |
#' correct. | |
#' @param token JWT extracted with jose::jwt_decode_hmac. | |
#' @param claims named list of claims to check in the JWT. Claims can be nested. | |
#' @return TRUE if the all claims are present in the JWT, FALSE if not. | |
#' @importFrom purrr map2_lgl | |
#' @export | |
check_all_claims <- function(token, claims){ | |
claim_values <- claims | |
claim_names <- names(claims) | |
results <- purrr::map2_lgl(claim_names, claim_values, check_claim, token = token) | |
return(all(results)) | |
} | |
#' | |
#' This function checks that a claim passed to the jwt function is valid in the | |
#' given JWT. | |
#' A claim consists of a claim name (e.g. "iss") and a claim value (e.g. "company A"). | |
#' Claim values can also be named lists themselves. | |
#' The function recursively extracts the value for claim_name from the token. | |
#' If the claim_value is atomic, it compares | |
#' the retrieved value with the claimed value. Otherwise, it applies check_claim | |
#' to claim_value recursively. | |
#' @param claim_name name of the claim in the JWT, e.g. "iss". | |
#' @param claim_value value the claim should have to pass the test. | |
#' @param token JWT extracted with jose::jwt_decode_hmac. | |
#' @return TRUE if the claim is present in the JWT, FALSE if not. | |
#' @importFrom purrr vec_depth map2_lgl | |
#' @export | |
check_claim <- function(claim_name, claim_value, token){ | |
# recursion at end, claim_value is just atomic (e.g. "Alice") | |
if(purrr::vec_depth(claim_value) == 1){ | |
token_claim_value <- token[[claim_name]] | |
# claim does not exist in token | |
if (is.null(token_claim_value)) { | |
return(FALSE) | |
} | |
# compare token value with expected value | |
return(identical(token_claim_value, claim_value)) | |
} else { | |
# claim_value is a list --> recurse | |
# cannot subset token because claim_name does not exist in token | |
# -> wrong claim_value | |
if (!claim_name %in% names(token)){ | |
return(FALSE) | |
} | |
# recursively apply to all elements of claim_value | |
return(all(c(purrr::map2_lgl(names(claim_value), claim_value, check_claim, | |
token = token[[claim_name]])))) | |
} | |
} | |
TEST_TOKEN <- list(iss = "plu", | |
user = list( | |
name = list( | |
lastname = "Smith", | |
firstname = "Alice"), | |
id = "1234", | |
admin = TRUE | |
), | |
iat = 123456789, | |
company = list( | |
id = 1, | |
name = "a plumber company" | |
)) | |
check_all_claims(TEST_TOKEN, claims = list( | |
user = list(admin = TRUE), | |
company = list(id = 1), | |
iss = "plu" | |
)) | |
# FALSE | |
check_all_claims(TEST_TOKEN, claims = list( | |
user = list(admin = TRUE, id = "5678"), | |
company = list(id = 1), | |
iss = "plu" | |
)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment