1/*
2 * Copyright 2023, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7#include "JwtTokenHelper.h"
8
9#include "DataIOUtils.h"
10#include "Json.h"
11#include "JsonMessageWriter.h"
12
13#include <ctype.h>
14
15
16/*static*/ bool
17JwtTokenHelper::IsValid(const BString& value)
18{
19	int countDots = 0;
20
21	for (int i = 0; i < value.Length(); i++) {
22		char ch = value[i];
23
24		if ('.' == ch)
25			countDots++;
26		else {
27			if (!_IsBase64(ch))
28				return false;
29		}
30	}
31
32	return 2 == countDots;
33}
34
35
36/*! A JWT token is split into three parts separated by a '.' character. The
37    middle section is a base-64 encoded string and within the string is JSON
38    structured data. The JSON data contains key-value pairs which carry data
39    about the token. This method will take a JWT token, will find the middle
40    section and will parse the claims into the supplied 'message' parameter.
41*/
42
43/*static*/ status_t
44JwtTokenHelper::ParseClaims(const BString& token, BMessage& message)
45{
46	int firstDot = token.FindFirst('.');
47
48	if (firstDot == B_ERROR)
49		return B_BAD_VALUE;
50
51	// find the end of the first section by looking for the next dot.
52
53	int secondDot = token.FindFirst('.', firstDot + 1);
54
55	if (secondDot == B_ERROR)
56		return B_BAD_VALUE;
57
58	BMemoryIO memoryIo(&(token.String())[firstDot + 1], (secondDot - firstDot) - 1);
59	Base64DecodingDataIO base64DecodingIo(&memoryIo, '-', '_');
60	BJsonMessageWriter writer(message);
61	BJson::Parse(&base64DecodingIo, &writer);
62
63	return writer.ErrorStatus();
64}
65
66
67/*! Note this is base64 "url" standard that disallows "/" and "+" and instead
68    uses "-" and "_".
69*/
70
71/*static*/ bool
72JwtTokenHelper::_IsBase64(char ch)
73{
74	return isalnum(ch)
75		|| '=' == ch
76		|| '-' == ch
77		|| '_' == ch;
78}
79