<p>Wer sich mit Authentifizierung im Web befasst wird früher oder später auf den Begriff <a href="http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html">JSON Web Token treffen (JWT)</a>. </p>
<p>Was ist ein JWT?<br />
Vermutlich nutze ich nicht die Security-Fach-Termini, aber seis drum: JWTs werden eingesetzt um Claims zwischen zwei Systemen auszutauschen. Beispiel: Über eine App möchte man sich an einem Dienst (Facebook, Twitter, etc.) einloggen und seine Daten sehen. Als Rückantwort von dem Dienst kommt ein JWT welches die Claims des authentifizierten und authorisierten Nutzers enthält. Ein Claim ist im Grunde nur ein Key/Value Pair wo man so ziemlich alles unterbringen kann was man sich vorstellen kann.</p>
<p>Die volle Spezifikation enthält dazu wesentlich mehr <a href="http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html">Informationen</a>.</p>
<p>Wozu eigene JWTs?</p>
<p>Wer bereits sein eigenes Authentifizierungssystem am laufen hat und nun ebenfalls eine OAuth Schnittstelle anbieten möchte (für Apps), der wird früher oder später sich damit befassen wie sich Clients am System anmelden können. Das JWT kann dann als Transportmedium dienen.</p>
Eigene JWTs erstellen & validieren
<p>Mit dem .NET Framework 4.5 und <a href="https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/">JSON Web Token Handler</a> NuGet Package kann man sowohl Tokens von anderen Diensten validieren oder auch selber welche erstellen. Der <a href="http://pfelix.wordpress.com/2012/11/27/json-web-tokens-and-the-new-jwtsecuritytokenhandler-class/">Code stammt zu 99% aus diesem Blog</a>, welcher noch weitere Security und HTTP Themen behandelt.</p>
1: // Code source is from this awesome blog:
<p>
2: // http://pfelix.wordpress.com/2012/11/27/json-web-tokens-and-the-new-jwtsecuritytokenhandler-class/
<p>
3: class Program
<p>
4: {
<p>
5: static void Main(string[] args)
<p>
6: {
<p>
7: var securityKey = GetBytes("ThisIsAnImportantStringAndIHaveNoIdeaIfThisIsVerySecureOrNot!");
<p>
8:
<p>
9: var tokenHandler = new JwtSecurityTokenHandler();
<p>
10:
<p>
11: // Token Creation
<p>
12: var now = DateTime.UtcNow;
<p>
13: var tokenDescriptor = new SecurityTokenDescriptor
<p>
14: {
<p>
15: Subject = new ClaimsIdentity(new Claim[]
<p>
16: {
<p>
17: new Claim(ClaimTypes.Name, "Pedro"),
<p>
18: new Claim(ClaimTypes.Role, "Author"),
<p>
19: }),
<p>
20: TokenIssuerName = "self",
<p>
21: AppliesToAddress = "http://www.example.com",
<p>
22: Lifetime = new Lifetime(now, now.AddMinutes(2)),
<p>
23: SigningCredentials = new SigningCredentials(
<p>
24: new InMemorySymmetricSecurityKey(securityKey),
<p>
25: "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
<p>
26: "http://www.w3.org/2001/04/xmlenc#sha256"),
<p>
27: };
<p>
28: var token = tokenHandler.CreateToken(tokenDescriptor);
<p>
29:
<p>
30: // Generate Token and return string
<p>
31: var tokenString = tokenHandler.WriteToken(token);
<p>
32: Console.WriteLine(tokenString);
<p>
33:
<p>
34: // Token Validation
<p>
35: var validationParameters = new TokenValidationParameters()
<p>
36: {
<p>
37: AllowedAudience = "http://www.example.com",
<p>
38: SigningToken = new BinarySecretSecurityToken(securityKey),
<p>
39: ValidIssuer = "self"
<p>
40: };
<p>
41:
<p>
42: // from Token to ClaimsPrincipal - easy!
<p>
43: var principal = tokenHandler.ValidateToken(tokenString, validationParameters);
<p>
44:
<p>
45: Console.WriteLine(principal.Claims.Single(x => x.Type == ClaimTypes.Name).Value);
<p>
46:
<p>
47: Console.ReadLine();
<p>
48: }
<p>
49:
<p>
50: static byte[] GetBytes(string str)
<p>
51: {
<p>
52: byte[] bytes = new byte[str.Length * sizeof(char)];
<p>
53: System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
<p>
54: return bytes;
<p>
55:
<p>
56: }
<p>
57: }
<p>
Erklärung
<p>Im ersten Schritt wird ein SecurityKey erzeugt – dieser wird für den TokenHandler benötigt. In diesem Fall ist es ein symetrischer Schlüssel, d.h. beide Partein benötigen den vollen Schlüssel. Ein JWT kann man mit den unterschiedlichsten Verfahren sichern (Zertifikate etc.). </p>
<p>Über den Token Handler gibt man einen ClaimsPrincipal rein – diese Claims möchten wir am Ende wieder lesen können.</p>
<p>Der Token wird erstellt mit allen Parametern und mit denselben Parametern und dem Schlüssel kann das Token wieder lesbar gemacht werden.</p>
<p>Diesen Token könnte man auch zwischen Server Applikationen austauschen lassen oder zwischen App und Service.</p>
<p>Das Bild zeigt die Ausgabe des Programms: Den Token und am Ende den “Name”-Claim.</p>
<p><a href="http://code-inside.de/blog/wp-content/uploads/image1929.png"></a></p>
<p>Der Code ist natürlich auch auf <a href="https://github.com/Code-Inside/Samples/tree/master/2013/JwtSampleApp">GitHub</a> verfügbar.</p>
<p>Was ist ein JWT?<br />
Vermutlich nutze ich nicht die Security-Fach-Termini, aber seis drum: JWTs werden eingesetzt um Claims zwischen zwei Systemen auszutauschen. Beispiel: Über eine App möchte man sich an einem Dienst (Facebook, Twitter, etc.) einloggen und seine Daten sehen. Als Rückantwort von dem Dienst kommt ein JWT welches die Claims des authentifizierten und authorisierten Nutzers enthält. Ein Claim ist im Grunde nur ein Key/Value Pair wo man so ziemlich alles unterbringen kann was man sich vorstellen kann.</p>
<p>Die volle Spezifikation enthält dazu wesentlich mehr <a href="http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html">Informationen</a>.</p>
<p>Wozu eigene JWTs?</p>
<p>Wer bereits sein eigenes Authentifizierungssystem am laufen hat und nun ebenfalls eine OAuth Schnittstelle anbieten möchte (für Apps), der wird früher oder später sich damit befassen wie sich Clients am System anmelden können. Das JWT kann dann als Transportmedium dienen.</p>
Eigene JWTs erstellen & validieren
<p>Mit dem .NET Framework 4.5 und <a href="https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/">JSON Web Token Handler</a> NuGet Package kann man sowohl Tokens von anderen Diensten validieren oder auch selber welche erstellen. Der <a href="http://pfelix.wordpress.com/2012/11/27/json-web-tokens-and-the-new-jwtsecuritytokenhandler-class/">Code stammt zu 99% aus diesem Blog</a>, welcher noch weitere Security und HTTP Themen behandelt.</p>
1: // Code source is from this awesome blog:
<p>
2: // http://pfelix.wordpress.com/2012/11/27/json-web-tokens-and-the-new-jwtsecuritytokenhandler-class/
<p>
3: class Program
<p>
4: {
<p>
5: static void Main(string[] args)
<p>
6: {
<p>
7: var securityKey = GetBytes("ThisIsAnImportantStringAndIHaveNoIdeaIfThisIsVerySecureOrNot!");
<p>
8:
<p>
9: var tokenHandler = new JwtSecurityTokenHandler();
<p>
10:
<p>
11: // Token Creation
<p>
12: var now = DateTime.UtcNow;
<p>
13: var tokenDescriptor = new SecurityTokenDescriptor
<p>
14: {
<p>
15: Subject = new ClaimsIdentity(new Claim[]
<p>
16: {
<p>
17: new Claim(ClaimTypes.Name, "Pedro"),
<p>
18: new Claim(ClaimTypes.Role, "Author"),
<p>
19: }),
<p>
20: TokenIssuerName = "self",
<p>
21: AppliesToAddress = "http://www.example.com",
<p>
22: Lifetime = new Lifetime(now, now.AddMinutes(2)),
<p>
23: SigningCredentials = new SigningCredentials(
<p>
24: new InMemorySymmetricSecurityKey(securityKey),
<p>
25: "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
<p>
26: "http://www.w3.org/2001/04/xmlenc#sha256"),
<p>
27: };
<p>
28: var token = tokenHandler.CreateToken(tokenDescriptor);
<p>
29:
<p>
30: // Generate Token and return string
<p>
31: var tokenString = tokenHandler.WriteToken(token);
<p>
32: Console.WriteLine(tokenString);
<p>
33:
<p>
34: // Token Validation
<p>
35: var validationParameters = new TokenValidationParameters()
<p>
36: {
<p>
37: AllowedAudience = "http://www.example.com",
<p>
38: SigningToken = new BinarySecretSecurityToken(securityKey),
<p>
39: ValidIssuer = "self"
<p>
40: };
<p>
41:
<p>
42: // from Token to ClaimsPrincipal - easy!
<p>
43: var principal = tokenHandler.ValidateToken(tokenString, validationParameters);
<p>
44:
<p>
45: Console.WriteLine(principal.Claims.Single(x => x.Type == ClaimTypes.Name).Value);
<p>
46:
<p>
47: Console.ReadLine();
<p>
48: }
<p>
49:
<p>
50: static byte[] GetBytes(string str)
<p>
51: {
<p>
52: byte[] bytes = new byte[str.Length * sizeof(char)];
<p>
53: System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
<p>
54: return bytes;
<p>
55:
<p>
56: }
<p>
57: }
<p>
Erklärung
<p>Im ersten Schritt wird ein SecurityKey erzeugt – dieser wird für den TokenHandler benötigt. In diesem Fall ist es ein symetrischer Schlüssel, d.h. beide Partein benötigen den vollen Schlüssel. Ein JWT kann man mit den unterschiedlichsten Verfahren sichern (Zertifikate etc.). </p>
<p>Über den Token Handler gibt man einen ClaimsPrincipal rein – diese Claims möchten wir am Ende wieder lesen können.</p>
<p>Der Token wird erstellt mit allen Parametern und mit denselben Parametern und dem Schlüssel kann das Token wieder lesbar gemacht werden.</p>
<p>Diesen Token könnte man auch zwischen Server Applikationen austauschen lassen oder zwischen App und Service.</p>
<p>Das Bild zeigt die Ausgabe des Programms: Den Token und am Ende den “Name”-Claim.</p>
<p><a href="http://code-inside.de/blog/wp-content/uploads/image1929.png"></a></p>
<p>Der Code ist natürlich auch auf <a href="https://github.com/Code-Inside/Samples/tree/master/2013/JwtSampleApp">GitHub</a> verfügbar.</p>
36.765 mal gelesen