get the solution


Page 1 of 3123

Add Token Authorization to AngularJS and WebApi

By
on Regards: .NET Framework; C#;

Protection and authorization for a Single Web Application and a RESTFul Service

Introduction

There exists some ways to implement an authentication into RESTFul Service. For this article I will focus on the HTTP Token Header technique, because its really easy to implement with the JsonWebTokenHandler.(RESTful Authentication, 22.08.2015, http://stackoverflow.com/questions/319530/restful-authentication?lq=1  ).

To keep it short we focus on the practical aspect. The demonstration contains a Single Web Application with AngularJS which is hosted on an ASP.NET MVC page. The RESTFul Service will be represented by an ASP.NET WebApi project. I want to mention that most of the code was built from code snippets which I researched from other blogs or stackoverflow to reduce time. So the example project consists of several code snippets and some custom coding.

As you know the RESTFul Service is stateless. We need to achieve that the WebApi can correctly identify our current requests to a user. There the token, or precisely the Json Web Token, comes into play. Because the returned data is formatted as JSON the term Json Web Token is more common in that subject.

When sending a valid login request to the WebApi, it will issue a token for the logged in user. The SWA will catch the returned token from the login. From now the SWA will add the token to each call into the HTTP Header. The WebApi will check if there exists a JWT and extract the containing user information. This process is visualized in the graphic below.

Description of the Security token service

After associating a user to the request we can permit or deny the request.

{"iss":"Identity Provider","name":"John Doe","admin":true}

The Json Web Token is a JSON-based open standard which contains the user payload a signature and the following important header information’s (JSON Web Token, https://en.wikipedia.org/wiki/JSON_Web_Token, 22.08.2015).

  • Issuer (iss) : The Service which created the jwt
  • Subject (sub) : The subject regarding the token
  • Audience (aud) : Which application can use the token
  • Expiration time (exp): When expires the token
  • Not before (nbf): Don’t use the token before
  • Issued at (iat): When was the token created
  • JWT ID (jti) : The ID of the token

(“JSON Web Token (JWT)”, https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html, 22.08.2015 )

Frontend – AngularJS

Our AngularJS web application has got an Authentication service which can initiate the login process. It sends the logon and the password to the webapi and saves the returned token. The token will be set to the default Authorization HTTP Header of the httpService (“Setting angularjs $http headers globally“, http://stackoverflow.com/questions/27134840/setting-angularjs-http-headers-globally, 22.08.2015).

In order to prevent the user from navigating to any other page of our application, we add a callback to the angular module. When navigating between pages the callback checks if the user is logged in our Authentication service.

This is done by registering the “$locationChangeStart” event which will be fired on any page navigation. If the user is not logged in we force a redirect to the login page. A logout can be done by refreshing the whole page, the state of the SWA will then be lost.

After a successful login we forward the user from the login- to the home view. The corresponding homeController makes an authenticated webapi request which will then return the current users privileges.

Backend – WebApi

Let’s switch to the WebApi’s PostUser action method. It is used to login a user and issue a security json web token.

First of all we check if the delivered user credentials are correct. Normally this is done by querying the database or another resource. The user and the roles are implemented with the claims-based identity of the Windows Identify Foundation. So if you never heard of claims you should definitely check Andras Nemes blog series about that topic (“Introduction to Claims based security in .NET4.5 with C# Part 4: authorisation with claims”, http://dotnetcodr.com/2013/02/21/introduction-to-claims-based-security-in-net4-5-with-c-part-4-authorisation-with-claims/, 22.08.2015 ).

For creating JSON Web Tokens Microsoft published the JwtSecurityTokenHandler class which can be found in the NuGet Package System.IdentityModel.Tokens.Jwt.

We create the ClaimsIdentity for the user which we wish to log in by adding his claims. After that we can create the token with tokenHandler.CreateToken(issuer: “http://localhost”, audience: “http://localhost”, subject: claimsIdentity, expires: expires, signingCredentials: new X509SigningCredentials(cert));

So as you see the issuer and audience value are equal because we create the token and at the same time consume it. With the expire parameter we can determine how long the token is valid and with the signing credentials we sign our token against manipulation. The returned encoded token is a base64 string.

The Json Web Token will be signed when issuing it with a private key. When a token will be “read”, it will be validated against the public key.

In this project I deposit the private and the public key as files, which is not recommended regarding security issues. In a real world example it would be stored in the certificate manager and for a convenient project start up I skipped that part. By the way, I used the following self-signed certificate tool http://blog.pluralsight.com/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net.

We should not only be able to create tokens, but also to read and “extract” the information from it. This can be done with a DelegatingHandler which intercepts every web request of the WebApi.

Vittorio Bertocci wrote an excellent article http://www.cloudidentity.com/blog/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas/on that topic a while ago. The JwtSecurityTokenHandler has changed since the article was released.

What does the TokenValidationHandler do in particular?

First of all it intercept the web request before the concerning action method gets executed. It checks if the request contains a HTTP Header with the key Authorization. If not, the request will be forwarded to the action method. If you wish to protect the action method you can add a claimsauthorization attribute (details about that later).

If there exists a JWT token it will be validated against the TokenValidationParameters and the public key. With ValidateToken the user information from the token will be extracted and set the current user of the HttpContext and Thread. If the validation didn’t fail the request will be forwarded to the action method. Otherwise we abort the current request and return an unauthorized status code.

If for specific action methods certain claims are necessary we can use the ClaimsAuthorization attribute. Before the action method gets executed, it checks if the current HttpContext.User got the required claims.

The order how the web request is processed

Remarks

The solution is configured in a way that you can easily execute the project. Make sure you installed Visual Studio 2013 with the Web Development Tools and the latest updates. Also The Web Essential Tools should be installed with the latest TypeScript Version. You can Download the project from Github.

Press F5 to start the Web Project and navigate to http://localhost:5118/Default/Index/to start the SWA. Then switch to Visual Studio and right click on the WebApi Project and select Debug àStart new Instance. Create some breakpoints and try to login with the user martin in the web application and step through the program to see what’s happening.

Because the web projects are hosted under different domains (http://localhost:5118vs http://localhost:5117) we run into the CORS issue. To solve that I installed the CORS NuGet Package from Microsoft and enabled it with the EnableCors attribute. You may also want to check http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api.

I hope I could show you that it is really is easy to implement an authentication mechanism in AngularJS and ASP.NET WebApi. If you have any questions or suggestion feel free to comment or write me on twitter.

Other used Links:

http://stackoverflow.com/questions/18032038/securing-the-jwt-with-a-x509certificate2-jwtsecuritytokenhandler create jwt token

http://stackoverflow.com/questions/20198124/read-private-key-from-pfx-file read certificate from file

http://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in get current assemply path


Page 1 of 3123

DLL Hell – Could not load file or assembly System.Web.http 4.0.0.0

By
on Regards: .NET Framework;

Bei einem Erstdeployment kann es zu unliebsamen Überraschungen kommen bei denen nicht sofort die Ursache erkennbar ist.

Besonders tragisch ist es, wenn die Fehlermeldung am Testsystem nicht am Entwicklungssystem reproduzierbar ist. Nach dem Installieren und Aufrufen der Applikation wird vom IIS die Fehlermeldung “Could not load file or assembly System.Web.http 4.0.0.0” ausgegeben.

Die StackOverFlow Antworten brachten keine Lösung, weshalb das Problem genauer anlysiert werden musste.

Das Testsystem war eine Windows Server 2003 Installation und siehe da, im GAC war tatsächlich die Datei nicht vorhanden. Der Global Assembly Cache ist dazu da, um Versionskonflikte zu vermeiden. Ein weiteres Feature vom GAC ist, das die Assemblies dort nativ vorliegen. Während der Installation vom .NET Framework werden die Assemblies prozessoroptimiert kompiliert und sind dann in nativem Code verfügbar. Das heißt die Bibliotheken können um einiges schneller gestartet werden, als die “üblichen” welche in der Common Intermediate Language vorliegen und mit dem JIT ausgewertet werden.

Wie auch immer, nach Recherechen hat sich dann herausgestellt, dass genau diese File und noch ein paar Andere auf Server Installationen nicht ausgeliefert werden (Security Issues).

Also habe ich die Option Copy to Local im Visual Studio auf true gesetzt. Auch das zeigte keinen Effekt. Somit löschte ich die Referenz und kompilierte nochmal das Projekt auf dem Entwicklungssystem. Trotz der Änderung kam am Testsystem nach wie vor die Fehlermeldung. Also die Änderung wieder Rückgäng machen und die Referenz System.Web.http zum Projekt hinzufügen.

Nach dem die Projekt-Referenzen genauer unter die Lupe genommen wurden, fiel eine Third Party Referenz auf, die eine Abhänigkeit auf System.Web.http hatte. Außerdem waren die referenzierten Versionen auf System.Web.http der Lib und der Web Application unterschiedlich. Es wurden deshalb alle Referenzen von System.Web.Http zunächst einmal auf die Version upgedated welche die Third Party Lib verwendete. In der web.config ist auch der Eintrag

 < dependentAssembly>
    < assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
    < bindingRedirect oldVersion="0.0.0.0-5.3.0.0" newVersion="5.3.0.0" />
 < / dependent Assembly > 

interessant. Den dieser ist dafür verantwortlich, dass wenn keine geeignete Assembly Version gefunden wird, ein Fallback auf den GAC passiert. Genau das ist auf der Testmaschine passiert. Die Assembly System.Web.http war im bin Folder der Web Application vorhanden, aber aufgrund des web.config Eintrag wurde stattdessen auf den GAC zurückgegriffen. Da auf der Windows Server Installation die File nicht existierte, kam die Fehlermeldung. Auf dem Entwicklungsystem waren beide Assembly Versionen vorhanden, weshalb der Fehler so nicht reproduzierbar war.

Nachdem bei allen Projekten die Referenzen auf die korrekte Assembly Version verwiesen haben kam immer noch die Fehlermeldung System.Web.Http 4.0.0.0 wurde nicht gefunden, obwohl die neue Assembly Version 5.3.0.0 lauten sollte. Nach weiterem suchen, hat sich herausgestellt, dass die Projektdateien im Visual Studio zwei Referenzen auf die gleiche Assembly hatten mit jeweils der unterschiedlichen Assembly Version. In diesem Fall hat die Visual Studio GUI die falsche Information angezeigt. Das Visual Studio Projekt musste also ungeloaded werden und in der xml Ansicht nachbearbeitet um die alten Assembly Verweise zu löschen. Der Fehler könnte von einem auto. TFS merge stammen.

In diesem Fall haben mehrere ungünstige Faktoren zusammengespielt.


Page 1 of 3123

Datenbankoptimierung

By
on Regards: C#; DBMS;

Hier möchte ich kurz einige Begriffe und Möglichkeiten in den Raum werfen die bei Datenbankoptimierungen eine Rolle spiele können. Hier noch ein guter Link http://www.codeproject.com/Articles/35665/Top-steps-to-optimize-data-access-in-SQL-Serv
  • Query optimieren (z.B. mit Include Actual Execution Plan)
  • Tabelle partitionieren wenn es Sinn macht
  • Indexes anlegen
    • Geht auch bei Views
    • Sollten von Zeit zu Zeit aktualisiert werden ansonsten hat man gleich wieder Performance einbußen
      • z.B. mit einem User Agent Job
  • DB Schema anpassen
    • Schneeflockenschema
    • Computed Values durch statisch Werte ersetzen – > die Werte können dann von einem Agent Job aktualisiert werden
  • Kimball and Ross http://www.codeproject.com/Articles/647950/Create-and-Populate-Date-Dimension-for-Data-Wareho
  • Hardware des Datenbank Server upgraden

Verwandte Themen: Datenbank erstellen mit dem ER-Diagramm und MySql


Page 1 of 3123

Email Subject mit UTF8 im Header

By
on Regards: C#; DBMS;

Emails sind laut Spezifikation in ASCII codiert weshalb man bei der Darstellung der Zeichen im Email sehr beschränkt ist.

Es gibt zwar die Möglichkeit im Header mit der Eigenschaft Content-Type (Content-Type: text/plain; charset=UTF-8) die Codierung mit anzugeben damit der Email Client weiß wie der Content Body codiert ist. Jedoch trifft das eben nicht auf den Header zu. Wie kann man dann also das Subject im Header mit UTF-8 codieren?

Um im Header die ASCII beschränkung zu umgehen gibt es die “MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text” RFC Erweiterung. Der Emailclient muss diese RFC Erweiterung natürlich auch unterstützen. Diese RFC beschreibt zwei Möglichkeiten das Subject in einer anderen Codierung an zu geben.

  • Quoted Printable (subject starts with “=?utf-8?Q”)
  • Base64 (subject starts with “=?utf-8?B”)

Wir beschränken uns fürs erste auf die Base64 Variante da sie im Vergleich zur ersten weniger Zeichen benötigt.

Der Aufbau des Headers hat somit wie folgt aus zu sehen:

=?charset?B?text?=

Den Subject Text codieren wir in einen base64 String. Entweder ihr macht das per Code oder schnell online (https://www.base64encode.org/).

Anschließend muss man nur noch das Subject setzen. Kann z.B. so aussehen:

EXEC MSDB.dbo.sp_send_dbmail […] @subject = ‘=?UTF-8?B?base64text?=’

Links:


Page 1 of 3123