Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
advancedrei committed Feb 24, 2014
0 parents commit 91272f9
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
170 changes: 170 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#################
## Eclipse
#################

*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath


#################
## Visual Studio
#################

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.sln.docstates
*.tss
*.nupkg


# Build results
[Dd]ebug/
[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover

## TODO: If you have NuGet Package Restore enabled, uncomment this
packages/
#!src/packages/Microsoft*/


# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf

# Visual Studio profiler
*.psess
*.vsp

# ReSharper is a .NET coding add-in
_ReSharper*

# Installshield output folder
[Ee]xpress

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish

# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects

# 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



############
## Windows
############

# Windows image file caches
Thumbs.db

# Folder config file
Desktop.ini


#############
## Python
#############

*.py[co]

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox

#Translations
*.mo

#Mr Developer
.mr.developer.cfg

# Mac crap
.DS_Store

!*.targets
6 changes: 6 additions & 0 deletions .nuget/NuGet.Config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>
Binary file added .nuget/NuGet.exe
Binary file not shown.
23 changes: 23 additions & 0 deletions ClaimsFromJwt.nuspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>ClaimsFromJWT</id>
<version>1.0.0</version>
<title>Claims from JSON Web Token</title>
<authors>Matias Woloski, AdvancedREI</authors>
<owners>auth0, advancedrei</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://auth0.com</projectUrl>
<iconUrl>https://secure.gravatar.com/avatar/805765c256ff8617fcad483b5476faf2?s=420</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A set of helper functions that translate an already-validated JWT into a ClaimsIdentity, using standard Claims wherever possible.</description>
<copyright>Copyright © 2013-2014 Auth0 and AdvancedREI, LLC.</copyright>
<tags>jwt, webapi, Auth0, OAuth</tags>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.IdentityModel" targetFramework="" />
</frameworkAssemblies>
</metadata>
<files>
<file src="content\App_Start\ClaimsFromJwt.cs.pp" target="content\App_Start\ClaimsFromJwt.cs.pp" />
</files>
</package>
11 changes: 11 additions & 0 deletions DeployNuGet.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@echo off
echo Would you like to push the packages to NuGet when finished?
set /p choice="Enter y/n: "

del *.nupkg
@echo on
".nuget/nuget.exe" pack ClaimsFromJwt.nuspec
if /i %choice% equ y (
".nuget/nuget.exe" push *.nupkg
)
pause
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[ClaimsFromJWT 1.0](http://github.com/AdvancedREI/ClaimsFromJWT)=================ClaimsFromJWT is a set of helper functions to take a already-validated JWT and turn it into a ClaimsIdentity populated with as many standardized claims as possible.Quick start-----------Install the NuGet package: `Install-Package ClaimsFromJwt`, clone the repo, `git clone git://github.com/advancedrei/claimsfromjwt.git`, or [download the latest release](https://github.com/advancedrei/claimsfromjwt/zipball/master).Once the code has been installed, you can use the helper functions as needed. Deserialize the JWT into a Dictionary<string, object> and then pass that into JwtHelper.GetClaimsFromJwt().You can add to the arrays that map names to claims, or add additional claim mapping using the same technique. If you make any changes, consider sending us a pull request so that all can take advantage.Bug tracker-----------Have a bug? Please create an issue here on GitHub that conforms with [necolas's guidelines](https://github.com/necolas/issue-guidelines).https://github.com/AdvancedREI/ClaimsFromJWT/issuesTwitter account---------------Keep up to date on announcements and more by following AdvancedREI on Twitter, [@AdvancedREI](http://twitter.com/AdvancedREI).Blog----Read more detailed announcements, discussions, and more on [The AdvancedREI Dev Blog](http://advancedrei.com/blogs/development).Author-------**Robert McLaws**+ http://twitter.com/robertmclaws+ http://github.com/advancedreiCopyright and license---------------------Copyright 2013-2014 Auth0, LLC. and AdvancedREI, LLC.The MIT License (MIT)Copyright (c) 2013-2014 Auth0, LLC. and AdvancedREI, LLC.Permission is hereby granted, free of charge, to any person obtaining a copy ofthis software and associated documentation files (the "Software"), to deal inthe Software without restriction, including without limitation the rights touse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ofthe Software, and to permit persons to whom the Software is furnished to do so,subject to the following conditions:- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESSFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS ORCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHERIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR INCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Expand Down
157 changes: 157 additions & 0 deletions content/App_Start/ClaimsFromJwt.cs.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Web.Script.Serialization;

namespace $rootnamespace$
{

/// <summary>
/// A set of helper functions for transforming an already-validated JWT into a ClaimsIdentity, using
/// standardized Claims wherever possible.
/// </summary>
public static class JwtHelper
{

#region Constants

private const string StringClaimValueType = "http://www.w3.org/2001/XMLSchema#string";

#endregion

#region Private Members

// NOTE: You can add to or modify these arrays as necessary. The routine will automatically remove
// any "_" characters.

private static readonly string[] ClaimTypesForUserId = { "userid" };
private static readonly string[] ClaimTypesForRoles = { "roles", "role" };
private static readonly string[] ClaimTypesForEmail = { "emails", "email" };
private static readonly string[] ClaimTypesForGivenName = { "givenname", "firstname" };
private static readonly string[] ClaimTypesForFamilyName = { "familyname", "lastname", "surname" };
private static readonly string[] ClaimTypesForPostalCode = { "postalcode" };
private static readonly string[] ClaimsToExclude = { "iss", "sub", "aud", "exp", "iat", "identities" };

#endregion

#region Public Methods

/// <summary>
/// Gets a List of Claims from a given deserialized JSON token.
/// </summary>
/// <param name="jwtData">The deserialized JSON payload to process.</param>
/// <param name="issuer">The principal that issued the JWT.</param>
/// <returns>A List of Claims derived from the JWT.</returns>
public static List<Claim> GetClaimsFromJwt(Dictionary<string, object> jwtData, string issuer)
{
var list = new List<Claim>();
issuer = issuer ?? DefaultIssuer;

foreach (var pair in jwtData)
{
var claimType = GetClaimType(pair.Key);
var source = pair.Value as ArrayList;

if (source != null)
{
// Get the claim, check to make sure it hasn't already been added. This is a workaround
// for an issue where MicrosoftAccounts return the same e-mail address twice.
foreach (var innerClaim in source.Cast<object>().Select(item => new Claim(claimType, item.ToString(), StringClaimValueType, issuer, issuer))
.Where(innerClaim => !list.Any(c => c.Type == innerClaim.Type && c.Value == innerClaim.Value)))
{
list.Add(innerClaim);
}

continue;
}

var claim = new Claim(claimType, pair.Value.ToString(), StringClaimValueType, issuer, issuer);
if (!list.Contains(claim))
{
list.Add(claim);
}
}

// dont include specific jwt claims
return list.Where(c => ClaimsToExclude.All(t => t != c.Type)).ToList();
}

/// <summary>
/// Gets a <see cref="ClaimsIdentity"/> properly populated with the claims from the JWT.
/// </summary>
/// <param name="claims">The list of claims that we've already processed.</param>
/// <param name="issuer">The principal that issued the JWT.</param>
/// <returns></returns>
public static ClaimsIdentity GetClaimsIdentity(List<Claim> claims, string issuer)
{
var subject = new ClaimsIdentity("Federation", ClaimTypes.Name, ClaimTypes.Role);

foreach (var claim in claims)
{
var type = claim.Type;
if (type == ClaimTypes.Actor)
{
if (subject.Actor != null)
{
throw new InvalidOperationException(string.Format(
"Jwt10401: Only a single 'Actor' is supported. Found second claim of type: '{0}', value: '{1}'", new object[] { "actor", claim.Value }));
}
}

var claim3 = new Claim(type, claim.Value, claim.ValueType, issuer, issuer, subject);
subject.AddClaim(claim3);
}

return subject;
}

/// <summary>
/// Attempts to map names from the JWT into standard Claim types.
/// </summary>
/// <param name="name">The name of the Claim as passed in my the JWT.</param>
/// <returns>A string that hopefully contains the standard namespace for a given Claim.</returns>
public static string GetClaimType(string name)
{
var newName = name.Replace("_", "").ToLower();
if (newName == "name")
{
return ClaimTypes.Name;
}
if (ClaimTypesForUserId.Contains(newName))
{
return ClaimTypes.NameIdentifier;
}
if (ClaimTypesForRoles.Contains(newName))
{
return ClaimTypes.Role;
}
if (ClaimTypesForEmail.Contains(newName))
{
return ClaimTypes.Email;
}
if (ClaimTypesForGivenName.Contains(newName))
{
return ClaimTypes.GivenName;
}
if (ClaimTypesForFamilyName.Contains(newName))
{
return ClaimTypes.Surname;
}
if (ClaimTypesForPostalCode.Contains(newName))
{
return ClaimTypes.PostalCode;
}
if (name == "gender")
{
return ClaimTypes.Gender;
}

return name;
}

#endregion

}
}

0 comments on commit 91272f9

Please sign in to comment.