Readdy Write  
0,00 €
Your View Money
Views: Count
Self 20% 0
Your Content 60% 0

Users by Links 0
u1*(Content+Views) 10% 0
Follow-Follower 0
s2*(Income) 5% 0

Count
Followers 0
Login Register as User

Example Code: Create Asp.Net Core Web API and exchange data with UWP Client App using jwtToken

28.06.2018 (👁35021)


 

Description:

This code example shows how to build a Web API (Restful Service) into a web page, secure access and transfer with jwtToken Java Web Tokens, and read and edit the data with a UWP client.

 

terms:

UWP Universal Windows Platform app

JWT Java Web Token

API application programming interface

C # code

 

 

 

 

Step 1: Requirements

Asp.Net Core: Insert Api Autorize with Jwt Tokens

 

Jwt = Java Web Tokens

 

requirements:

You have to insert the Microsoft NuGet Package System IdentityModel Tokens JWT

 

To do this, open the Asp Solution-> Contect menu-> Manage Nuget Packages

Then enter Browse-> jwt

 

System.IdentityModel.Tokens.Jwt

Includes types that provide support for creating, serializing and validating JSON Web Tokens.

 

Then under Asp.Net Core Project-> Dependencies-> NuGet

The entry: System.IdentityModel.Tokens.Jwt stand

 

 

And in addition the Microsoft.AspNetCore.Authentication.JwtBearer

 

 

Microsoft.AspNetCore.Authentication.JwtBearer

ASP.NET Core bearer token to OpenID Connect bearer token.

 

 

 

Step 2: Create Server TokenController

 

The data communication is protected by a backup token. To do this, the client app must first pick up a security token and pass it on as authorization in subsequent transfers.

The security token can be picked up in an Asp.Net controller.

The security token contains a key and a validity date known only to the server.

The security token becomes a user token by incorporating additional information into the token as claims. Here the user is entered as claim.

The claims can then be evaluated when inquiring about data and again checked against the user.

 

Through this additional information Claim.User in the token is also later guaranteed that each user can only read and write his own data.

 

Token controller

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

 

//< using >

using System.Text;                      //*Encoding

using Microsoft.IdentityModel.Tokens;   //*SymmetricSecurityKey

using System.Security.Claims;           //*Claims for JWT Token

using System.IdentityModel.Tokens.Jwt;  //*JwtRegisteredClaimNames

using Microsoft.Extensions.Primitives;  //StringValues

//</ using >

 

namespace Freelance.Controllers.api

{

    //*when open an api-Connection, first call /api/token and get a valid token to work with the api data

    [Produces("application/json")]

    public class TokenController : Controller

    {

        //--------------< Class: TokenController >---------------------

        //*min 16 chars

        SymmetricSecurityKey _secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27"));

 

 

        [Route("api/get_InitToken")]

        [HttpGet]

        public IActionResult Get_Init_Token()

        {

            //--------< Get_Init_Token >--------

            //--< Create a Token >--

            JwtSecurityToken jwtInitToken = new JwtSecurityToken(

                issuer: "website_freelancer",    //ASP.NET Core web application

                audience: "webclients_freelancer"//client app

                notBefore: DateTime.Now,

                expires: DateTime.Now.AddDays(1),

                signingCredentials: new SigningCredentials(_secretKey, SecurityAlgorithms.HmacSha256)

            );

            //--</ Create a Token >--

 

 

            string stringToken = new JwtSecurityTokenHandler().WriteToken(jwtInitToken);

 

            return Ok(stringToken);

            //--------</ Get_Init_Token() >--------

        }

 

 

 

        [Route("api/get_usertoken")]

        [HttpGet]

        public IActionResult Get_UserToken()

        {

            //-------------< Get_UserToken() >------------- 

            //*Create a Usertoken if parameters are correct.

 

 

            string username = "";

            string password = "";

 

            if (Request.Headers.TryGetValue("Authorization"out StringValues authToken))

            {

                string authHeader = authToken.First();

                string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();

                Encoding encoding = Encoding.UTF8; 

                string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));

                int seperatorIndex = usernamePassword.IndexOf(':');

                username = usernamePassword.Substring(0, seperatorIndex);

                password = usernamePassword.Substring(seperatorIndex + 1);

            }

            else

            {

                return BadRequest("Missing Authorization Header.");

            }

 

 

 

 

 

            //*check here against user and password

            if (check_login_user_password(username,password) == true)

            {

                //< login ok >

                string sToken = create_UserToken(username);

                return Content(sToken);

                //</ login ok >

            }

            else

            {

                //< login failed >

                return BadRequest();

                //</ login failed >

            }

 

            //-------------</ Get_UserToken() >------------- 

        }

 

 

 

        //*reference: www.blinkingcaret.com

        public string create_UserToken(string sUsername)

        {

            //-------------< create_UserToken() >-------------

            Claim[] claims = new Claim[] {

                new Claim(ClaimTypes.Name, sUsername), //*->User.Identity.Name or "Raimund Popp"

                new Claim(JwtRegisteredClaimNames.Email, "raimund.popp@codedocu.de")

 

            };

 

 

            //--< Create a Token >--

            JwtSecurityToken jwtToken = new JwtSecurityToken(

                issuer: "website_freelancer",    //ASP.NET Core web application

                audience: "webclients_freelancer"//client app

                claims: claims,

                notBefore: DateTime.Now,

                expires: DateTime.Now.AddDays(1),

                signingCredentials: new SigningCredentials(_secretKey, SecurityAlgorithms.HmacSha256)

            );

            //--</ Create a Token >--

 

 

            string stringToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);

 

            return stringToken;

            //-------------</ create_UserToken() >-------------

        }

 

 

 

 

        private bool check_login_user_password(string sUsername, string sPassword)

        {

            //-------------< check_login_user_password() >-------------

            //#todo: check user and password from user.

            return true;

            //-------------</ check_login_user_password() >-------------

        }

        //--------------</ Class: TokenController >---------------------

    }

}

 

 

 

 

Step 3: Authorize WebApi

 

Web API Controller

If the client later wants to fetch or write its data, it will switch to the WebApi controller.

This WebApi controller is usually located in a subdirectory / Api.

 

At the beginning of the controller call, access to the WebApi Controller is checked by preceding the authorization.

For this, the attribute: Authorize with the schema JwtBearer is to be inserted

[Authorize(AuthenticationSchemes = "JwtBearer")]    

 

WebApi Controller: Api / ProjectsController

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Freelance.Data;

using Freelance.Models;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

 

 

namespace Freelance.Controllers.api

{

    [Authorize(AuthenticationSchemes = "JwtBearer")]    //*goes to startup ConfigureServices.AddAuthentication->AddJwtBearer(..)

    [Produces("application/json")]

    [Route("api/Projects")]

    public class ProjectsController : Controller

    {

        //--------------< Class: ApiController >---------------------

        #region Controller Init

        private readonly ApplicationDbContext _dbContext;

        

        public ProjectsController(ApplicationDbContext dbContext)

        {

            //----< Init: Controller >----

            _dbContext = dbContext;

            //----</ Init: Controller >----

        }

        #endregion

 

 

        // GET: /api/index

        //[Authorize]

        public List<ProjectModel> Index()

        {

            ///-------------< Index >------------- 

 

            //--< Get Linq.Query >--

            //*gets last 10 Projects with View_Sum

            var query = (from n in _dbContext.tbl_Projects

                         where n.IsDraft == false

                         orderby n.IDProject descending

                         select  n ).Take(10);

            //--</ Get Linq.Query >--

 

            //----< fill Data_to_View >----

            List<ProjectModel> dataList = query.ToList<ProjectModel>();

         

            //< out >

            //*output to client

            return dataList;

            //</ out >

            ///-------------</ Index >------------- 

        }

       //--------------</ Class: ApiController  >---------------------

    }

}

 

 

 

Step 5: Insert Authorization Service

 

If a client application wants to open a Wep API (REST Service), then the attribute: Authorize in the controller will check.

[Authorize(AuthenticationSchemes = "JwtBearer")]    

 

The exam must be inserted as a schema in the Asp.Net Core Startup file in the Configure Services area

//----< JWT-Token >----

            //*reference: www.blinkingcaret.com

            services.AddAuthentication(options =>

            {

                options.DefaultAuthenticateScheme = "JwtBearer";

                options.DefaultChallengeScheme = "JwtBearer";

            })

 

            .AddJwtBearer("JwtBearer", jwtBearerOptions =>

            {

                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateIssuerSigningKey = true,

                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27")),

 

                    ValidateIssuer = true,

                    ValidIssuer = "website_freelancer",

 

                    ValidateAudience = true,

                    ValidAudience = "webclients_freelancer",

 

                    ValidateLifetime = true//validate the expiration and not before values in the token

 

                    ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date

                };

            });

            //----</ JWT-Token >----

 

As well as in Startup Block Configure the authorization has to be activated in general

            app.UseAuthentication();

 

 

Startup.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Identity;

using Microsoft.EntityFrameworkCore;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Freelance.Data;

using Freelance.Models;

using Freelance.Services;

using Microsoft.AspNetCore.Rewrite;

using Microsoft.AspNetCore.Http;

using Microsoft.IdentityModel.Tokens;   //*TokenValidationParameters

using System.Text;                      //*Encoding

 

namespace Freelance

{

    public class Startup

    {

 

 

        public Startup(IHostingEnvironment env)

        {

            var builder = new ConfigurationBuilder();

            builder.AddUserSecrets<Startup>();

 

            Configuration = builder.Build();

        }

 

        public IConfiguration Configuration { get; }

 

        // This method gets called by the runtime. Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {

            //-----------< ConfigureServices()  >-----------

            //Website_Constants.Connectionstring = Configuration["DefaultConnection"].ToString();

 

 

            services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Website_Constants.Connectionstring));

            //--< Identity >--

            services.AddIdentity<ApplicationUserIdentityRole>(config =>

            {

                //< send Register Email >

                //*prevents registered users from logging in until their email is confirmed.

                config.SignIn.RequireConfirmedEmail = true;

                //</ send Register Email >

            })

            .AddEntityFrameworkStores<ApplicationDbContext>()

            .AddDefaultTokenProviders();

            //--</ Identity >--

 

            //----< JWT-Token >----

            //*reference: www.blinkingcaret.com

            services.AddAuthentication(options =>

            {

                options.DefaultAuthenticateScheme = "JwtBearer";

                options.DefaultChallengeScheme = "JwtBearer";

            })

 

            .AddJwtBearer("JwtBearer", jwtBearerOptions =>

            {

                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateIssuerSigningKey = true,

                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27")),

 

                    ValidateIssuer = true,

                    ValidIssuer = "website_freelancer",

 

                    ValidateAudience = true,

                    ValidAudience = "webclients_freelancer",

 

                    ValidateLifetime = true//validate the expiration and not before values in the token

 

                    ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date

                };

            });

            //----</ JWT-Token >----

 

            // Add application services.

            services.AddTransient<IEmailSenderEmailSender>();

 

            var optRewrite = new RewriteOptions()

            .AddRedirectToHttpsPermanent();

 

 

            services.AddMvc();

 

            //-----------</ ConfigureServices() >-----------

        }

 

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)

        {

            //-----------< Configure() >-----------

            if (env.IsDevelopment())

            {

                app.UseBrowserLink();

                app.UseDeveloperExceptionPage();

                app.UseDatabaseErrorPage();

            }

            else

            {

                app.UseExceptionHandler("/Home/Error");

            }

 

            app.UseStaticFiles();

 

            app.UseAuthentication();

 

            app.UseMvc(routes =>

            {

 

 

 

                //--< Emoticons >--

                routes.MapRoute(

                   name: "🏠",

                   template: "🏠",

                   defaults: new { controller = "Home", action = "Index" }

               );

                routes.MapRoute(

                name: "📢",

                template: "📢",

                defaults: new { controller = "Home", action = "Index" }

                );

                routes.MapRoute(

                   name: "📜",

                   template: "📜",

                   defaults: new { controller = "Projects", action = "Index_all" }

                );

                //--</ Emoticons >--

 

                routes.MapRoute(

                   name: "Projects"// Route name

                   template: "Projects"// URL with parameters

                   defaults: new { controller = "Projects", action = "Index_all" }

               );

 

 

 

                routes.MapRoute(

                    name: "default",

                    template: "{controller=Projects}/{action=Index_all}/{id?}");

 

            }

            );

 

 

            //seed dbContext 

            Database.EF_Model.Initialize_DbContext_in_Startup(app.ApplicationServices);

            //-----------</ Configure()  >-----------

        }

    }

}

 

 

 

 

 

Step 6: Client access

 

Here the example of a UWP client

Client: UWP client

 

The client fetches a user token in the first step. It receives this token from the server under / api / get_usertoken.

For this purpose, you can initially transfer the user and password so that the user is entered as claim information in the UserToken.

            //-< get user token >-

            //*get the User-Password valid token 

            string sURL_Login = "http://localhost:51198/api/get_usertoken";

            var byteArray = Encoding.UTF8.GetBytes("MyUSER:MyPASS");

            var header = new AuthenticationHeaderValue("Basic"Convert.ToBase64String(byteArray));

            client.DefaultRequestHeaders.Authorization = header;

 

            string sUserToken = await client.GetStringAsync(sURL_Login);

            //-< get user token >-

 

 

Then the client can use this UserToken to fetch, read and edit their own data with the Web API Controller (REST Services).

//< read webApi >

            string sURL = "http://localhost:51198/api/projects";

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sUserToken);

            string sResponse_Projects = "";

            try

            {

                sResponse_Projects = await client.GetStringAsync(sURL);

            }

            catch (Exception ex)

            {

                string sMessage = ex.InnerException.ToString();

                MessageDialog dialog = new MessageDialog(sMessage, "Information");

                await dialog.ShowAsync();

                return;

            }

            //</ read webApi >

 

 

 

 

Client code

using System;

using System.Net;

using System.Net.Http;          //*HttpClient

using System.Net.Http.Headers;  //*AuthenticationHeaderValue

using System.Text;              //*Encoding

using Windows.Data.Json;        //*JsonObject

using Windows.UI.Popups;

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

 

 

namespace api01

{

 

    public sealed partial class MainPage : Page

    {

        public MainPage()

        {

            this.InitializeComponent();

        }

 

        private void btnStart_Click(object sender, RoutedEventArgs e)

        {

            read_API_Data();

 

        }

 

 

        public async void read_API_Data()

        {

            //---------------< read_API_Data() >---------------

 

            HttpClient client = new HttpClient();

 

            //-< get init token >-

            //*plain init-Token

            //string sURL_Login = "http://localhost:51198/api/get_InitToken";

            //string sToken = await client.GetStringAsync(sURL_Login);

            //-</ get init token >-

 

 

            //-< get user token >-

            //*get the User-Password valid token 

            string sURL_Login = "http://localhost:51198/api/get_usertoken";

            var byteArray = Encoding.UTF8.GetBytes("MyUSER:MyPASS");

            var header = new AuthenticationHeaderValue("Basic"Convert.ToBase64String(byteArray));

            client.DefaultRequestHeaders.Authorization = header;

 

            string sUserToken = await client.GetStringAsync(sURL_Login);

            //-< get user token >-

 

 

            //< read webApi >

            string sURL = "http://localhost:51198/api/projects";

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sUserToken);

            string sResponse_Projects = "";

            try

            {

                sResponse_Projects = await client.GetStringAsync(sURL);

            }

            catch (Exception ex)

            {

                string sMessage = ex.InnerException.ToString();

                MessageDialog dialog = new MessageDialog(sMessage, "Information");

                await dialog.ShowAsync();

                return;

            }

            //</ read webApi >

 

            

            //< get Json values >

            JsonArray jsonArray = JsonArray.Parse(sResponse_Projects);

            foreach (var jsonRow in jsonArray)

            {

                //----< json Row >----

                JsonObject jsonObject=jsonRow.GetObject();

 

                //< values >

                string IDProject= jsonObject["idProject"].ToString();

                string Title = jsonObject["title"].ToString();

                string Text = jsonObject["text"].ToString();

                string dtEdit = jsonObject["dtEdit"].ToString();

                //</ values >

 

                tbxResults.Text += Environment.NewLine + "-------";

                tbxResults.Text += Environment.NewLine + "idProject=" + IDProject;

                tbxResults.Text += Environment.NewLine + "Title=" + Title;

                tbxResults.Text += Environment.NewLine + "Text=" + Text;

                tbxResults.Text += Environment.NewLine + "dtEdit=" + dtEdit;

                //----</ json Row >----

            }

 

            //</ get Json values >

            //---------------</ read_API_Data() >---------------

        }

 

 

    }

}