Skip to content

Commit

Permalink
Evolving project to version 2.0 (#67)
Browse files Browse the repository at this point in the history
* Adding .editorconfig
* Setting version  to 2.0.0.0
* Removing reference to System.Web.Extensions, DefaultJsonSerializer. Adding Json.Net, JsonNetSerializer. Updating nuget packages for Tests
* Moving algorithm to separate classes. Adding AlgorithmFactory
* Adding JwtEncoder, moving Encode() methods to it
* Replacing MSTest with xUnit
* Moving serializers to the Serializers folder
* Refactoring tests
* Adding JwtDecoder, moving Decode() methods to it
* Moving validation to JwtValidator
* Calling JwtDecoder from static API
* Making verify parameter mandatory
* Upgrading to .NET 4.6.1
* Marking all static API as obsolete
* Sorting files in project file
* Updating nuspec, package.cmd, nuget.exe
* Adding IDateTimeProvider, DateTimeProvider. Using it in JwtValidator. Sealing all classes but exceptions.
* Bumping nuget package to 2.0.0-beta2
* Updating .gitignore
* Updating sln
* Moving Customer to Internal folder
* Adding JwtDecoderTest
* Adding JwtEncoderTest
* Do not instantiating new dictionary when no extra headers were passed to Encode()
* Passing verify as named parameter for readability. Other refactoring.
* Updating readme
* Renaming IAlgorithm to IJwtAlgorithm
* Removing Lazy<AlgorithmFactory>to make it just AlgorithmFactory
* Returning IDictionary<string, object> from non-generic DecodeToObject()
* Making AlgorithmFactory static field
  • Loading branch information
abatishchev authored Mar 7, 2017
1 parent 89d0e50 commit 6f398dc
Show file tree
Hide file tree
Showing 38 changed files with 1,494 additions and 854 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true;

[*]
end_of_line = crlf;

[*.cs]
indent_style = space;
indent_size = 4;
insert_final_newline = false;
trim_trailing_whitespace = true;
81 changes: 64 additions & 17 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,64 @@

#ignore thumbnails created by windows
Thumbs.db
#Ignore files build by Visual Studio
*.user
*.vspscc
*.suo
*.bak
[Bb]in
[Dd]ebug*/
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
package/
packages/
*.nupkg
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
package
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

#
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

9 changes: 7 additions & 2 deletions JWT.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
<package>
<metadata>
<id>JWT</id>
<version>1.4.1-beta</version>
<version>2.0.0-beta2</version>
<authors>John Sheehan, Michael Lehenbauer, Alexander Batishchev</authors>
<description>JWT (JSON Web Token) implementation for .NET</description>
<owners>johnsheehan, devinrader, abatishchev</owners>
<description>Jwt.Net, a JWT (JSON Web Token) implementation for .NET</description>
<copyright>Public Domain</copyright>
<language>en-US</language>
<projectUrl>https://github.com/jwt-dotnet/jwt</projectUrl>
<licenseUrl>https://creativecommons.org/publicdomain/zero/1.0/</licenseUrl>
<tags>jwt json</tags>
<dependencies>
<dependency id="Newtonsoft.Json" />
</dependencies>
</metadata>
</package>
71 changes: 37 additions & 34 deletions JWT.sln
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWT", "src\JWT\JWT.csproj", "{A80B51B8-DDF6-4026-98A4-B59653E50B38}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWT.Tests", "tests\JWT.Tests\JWT.Tests.csproj", "{BF568781-D576-4545-A552-4DC839B1AF14}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{513CE2B5-E0D6-43BC-998A-A02CB2875479}"
ProjectSection(SolutionItems) = preProject
JWT.nuspec = JWT.nuspec
package.cmd = package.cmd
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Release|Any CPU.Build.0 = Release|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWT", "src\JWT\JWT.csproj", "{A80B51B8-DDF6-4026-98A4-B59653E50B38}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWT.Tests", "tests\JWT.Tests\JWT.Tests.csproj", "{BF568781-D576-4545-A552-4DC839B1AF14}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{513CE2B5-E0D6-43BC-998A-A02CB2875479}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
JWT.nuspec = JWT.nuspec
package.cmd = package.cmd
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A80B51B8-DDF6-4026-98A4-B59653E50B38}.Release|Any CPU.Build.0 = Release|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF568781-D576-4545-A552-4DC839B1AF14}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
214 changes: 119 additions & 95 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,119 @@
# JSON Web Token (JWT) implementation for .NET

This library supports generating and decoding [JSON Web Tokens](http://tools.ietf.org/html/draft-jones-json-web-token-10).

## Installation
The easiest way to install is via NuGet. See [here](https://nuget.org/packages/JWT). Else, you can download and compile it yourself.

## Usage
### Creating Tokens

```csharp
var payload = new Dictionary<string, object>()
{
{ "claim1", 0 },
{ "claim2", "claim2-value" }
};
var secretKey = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
string token = JWT.JsonWebToken.Encode(payload, secretKey, JWT.JwtHashAlgorithm.HS256);
Console.WriteLine(token);
```

Output will be:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGFpbTEiOjAsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.8pwBI_HtXqI3UgQHQ_rDRnSQRxFL1SR8fbQoS-5kM5s

### Verifying and Decoding Tokens

```csharp
var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGFpbTEiOjAsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.8pwBI_HtXqI3UgQHQ_rDRnSQRxFL1SR8fbQoS-5kM5s";
var secretKey = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
try
{
string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey);
Console.WriteLine(jsonPayload);
}
catch (JWT.SignatureVerificationException)
{
Console.WriteLine("Invalid token!");
}
```

Output will be:

{"claim1":0,"claim2":"claim2-value"}

You can also deserialize the JSON payload directly to a .Net object with DecodeToObject:

```csharp
var payload = JWT.JsonWebToken.DecodeToObject(token, secretKey) as IDictionary<string, object>;
Console.WriteLine(payload["claim2"]);
```

which will output:

claim2-value

#### exp claim

As described in the [JWT RFC](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.4) the `exp` "claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing." If an `exp` claim is present and is prior to the current time the token will fail verification. The exp (expiry) value must be specified as the number of seconds since 1/1/1970 UTC.

```csharp
var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var now = Math.Round((DateTime.UtcNow - unixEpoch).TotalSeconds);
var payload = new Dictionary<string, object>()
{
{ "exp", now }
};
var secretKey = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
string token = JWT.JsonWebToken.Encode(payload, secretKey, JWT.JwtHashAlgorithm.HS256);

string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey); // JWT.SignatureVerificationException!
```

### Configure JSON Serialization

By default JSON Serialization is done by System.Web.Script.Serialization.JavaScriptSerializer. To configure a different one first implement the IJsonSerializer interface.

```csharp
public class CustomJsonSerializer : IJsonSerializer
{
public string Serialize(object obj)
{
// Implement using favorite JSON Serializer
}

public T Deserialize<T>(string json)
{
// Implement using favorite JSON Serializer
}
}
```

Next configure this serializer as the JsonSerializer.
```cs
JsonWebToken.JsonSerializer = new CustomJsonSerializer();
```
# Jwt.Net, a JWT (JSON Web Token) implementation for .NET

This library supports generating and decoding [JSON Web Tokens](http://tools.ietf.org/html/draft-jones-json-web-token-10).

## Installation
Package is avaliable via [NuGet](https://nuget.org/packages/JWT). Or you can download and compile it yourself.

## Supported .NET Framework versions
As of version 2.0, the lowest Supported version is 4.6.1

## Usage
### Creating (Encoding) Tokens

```csharp
var payload = new Dictionary<string, object>
{
{ "claim1", 0 },
{ "claim2", "claim2-value" }
};
var secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";

IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer);

var token = encoder.Encode(payload, secret);
Console.WriteLine(token);
```

Output will be:

>eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGFpbTEiOjAsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.8pwBI_HtXqI3UgQHQ_rDRnSQRxFL1SR8fbQoS-5kM5s
### Parsing (Decoding) and Verifying Tokens

```csharp
var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGFpbTEiOjAsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.8pwBI_HtXqI3UgQHQ_rDRnSQRxFL1SR8fbQoS-5kM5s";
var secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
try
{
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IJwtDecoder decoder = new JwtDecoder(serializer, validator);

var json = decoder.Decode(token, secret, verify: true);
Console.WriteLine(json);
}
catch (TokenExpiredException)
{
Console.WriteLine("Token has expired");
}
catch (SignatureVerificationException)
{
Console.WriteLine("Token has invalid signature");
}
```

Output will be:

>{ "claim1": 0, "claim2": "claim2-value" }
You can also deserialize the JSON payload directly to a .NET type with `DecodeToObject<T>`:

```csharp
var payload = decoder.DecodeToObject<IDictionary<string, object>>(token, secret);
Console.WriteLine(payload["claim2"]);
```

Output will be:

>claim2-value
#### exp claim

As described in the [JWT RFC](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.4), the `exp` "claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing." If an `exp` claim is present and is prior to the current time the token will fail verification. The exp (expiry) value must be specified as the number of seconds since 1/1/1970 UTC.

```csharp
IDateTimeProvider provider = new UtcDateTimeProvider();
var now = provider.GetNow();

var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var secondsSinceEpoch = Math.Round((now - unixEpoch).TotalSeconds);

var payload = new Dictionary<string, object>
{
{ "exp", secondsSinceEpoch }
};
var secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
var token = encoder.Encode(payload, secret);

var json = decoder.Decode(token, secret); // TokenExpiredException
```

### Custom JSON serializer

By default JSON serialization is done by JsonNetSerializer implemented using [Json.Net](https://www.json.net). To configure a different one first implement the `IJsonSerializer` interface:

```csharp
public class CustomJsonSerializer : IJsonSerializer
{
public string Serialize(object obj)
{
// Implement using favorite JSON Serializer
}

public T Deserialize<T>(string json)
{
// Implement using favorite JSON Serializer
}
}
```

And then pass this serializer as a dependency to JwtEncoder constructor:
```csharp
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new CustomJsonSerializer();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer);
```
Loading

0 comments on commit 6f398dc

Please sign in to comment.