-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJWTTokenHelpers.cs
More file actions
158 lines (141 loc) · 3.87 KB
/
Copy pathJWTTokenHelpers.cs
File metadata and controls
158 lines (141 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace Utils.Security.JWT
{
public class JWTTokenHelpers
{
internal static string JSONSerialize(dynamic payload)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(payload);
}
internal static string GetBase64URLEncoded(string raw)
{
string output = Convert.ToBase64String(Encoding.UTF8.GetBytes(raw));
output = output.Split('=')[0];
output = output.Replace('+', '-');
output = output.Replace('/', '-');
return output;
}
internal static JWTToken isValid<TPayload>(string token, KeyedHashAlgorithm algorithm, JWTAcceptedValues values) where TPayload : JWTPayload
{
List<string> tokenParts = new List<string>();
try
{
tokenParts = token.Split('.').ToList();
}
catch
{
throw new JWTExceptions.JWTSplitException("Token split exception");
}
if(tokenParts.Count != 3)
{
throw new JWTExceptions.JWTSplitException("Token doesnot have 3 parts");
}
string currentSignature = "";
try
{
currentSignature = JWTTokenHelpers.CreateSignature(tokenParts[0], tokenParts[1], algorithm);
currentSignature = GetBase64URLEncoded(currentSignature);
string oldSignature = tokenParts[2];
if(oldSignature == null || !oldSignature.Equals(currentSignature))
{
throw new JWTExceptions.JWTSignatureException("Signature invalid");
}
}
catch
{
throw new JWTExceptions.JWTSignatureException("Signature invalid");
}
try
{
for(int i = 0; i < 2; i++)
{
tokenParts[i] = GetBase64URLDecoded(tokenParts[i]);
}
}
catch
{
throw new JWTExceptions.JWTDecodingExceptions("Token parts are not decodable");
}
JWTHeader header = new JWTHeader();
TPayload payload;
try
{
header = JSONDesialize<JWTHeader>(tokenParts[0]);
payload = JSONDesialize<TPayload>(tokenParts[1]);
}
catch
{
throw new JWTExceptions.JWTDeserializeException("Data not parsable");
}
if(payload != null)
{
if(payload.ExpiryTime.Subtract(DateTime.Now) > values.ExpiryDuration)
{
throw new JWTExceptions.JWTExpiredException("JWT expired");
}
else if(payload.IpAddress == null || !payload.IpAddress.Equals(values.IpAddress))
{
throw new JWTExceptions.JWTIpAddressException("IP Address mismatch");
}
else if(payload.Audience == null || !payload.Audience.Equals(values.Audience))
{
throw new JWTExceptions.JWTIncorrectAudienceException("Audience incorrect");
}
else if(payload.Issuer == null || !payload.Issuer.Equals(values.Issuer))
{
throw new JWTExceptions.JWTIssuerIncorrectException("Issuer mismatch");
}
else
{
return new JWTToken()
{
Header = header,
Payload = payload,
Token = token
};
}
}
else
{
throw new JWTExceptions.JWTPayloadEmptyException("Payload null");
}
}
private static T JSONDesialize<T>(string v)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(v);
}
private static string GetBase64URLDecoded(string v)
{
string output = v;
output = output.Replace('-', '+');
output = output.Replace('_', '/');
switch(output.Length % 4)
{
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw new ArgumentOutOfRangeException(nameof(v), "Illegal base64url string");
}
byte[] converted = Convert.FromBase64String(output);
return Encoding.UTF8.GetString(converted);
}
internal static string CreateSignature(string headerEncoded, string payloadEncoded, KeyedHashAlgorithm algorithm)
{
string data = headerEncoded + "." + payloadEncoded;
byte[] encrypted = algorithm.ComputeHash(Encoding.UTF8.GetBytes(data));
return Encoding.UTF8.GetString(encrypted);
}
}
}