Setting up ASP.NET v5 (vNext) to use JWT tokens (using OpenIddict)

In this post,??I’ll show how I set up ASP.NET5 (vNext / ASP.NET Core / MVC6 / ASP.NET MVC Core) to use JWT tokens.

29 Jan 2016 UPDATE: The Github repo has been updated to include an AngularJS login.

First up, let me say I’m not expert on any of this, but if you see any??room for improvements / errors, please let me know.

TLDR:??If you don’t want to read the whole thing, you can download the finished code from:??

The website I??will be using this on is an AngularJS front end (although that’s not really relevant), which I hope to one day build mobile apps for, so JWT tokens seems like the logical choice.??My understanding is that I’d be using the??Resource Owner Flow of OAuth2; and that my authorization server (the thing that creates??the token) and my resource server (the thing that validates the token and returns the data – i.e. the API) would be in the same application. Also, users wouldn’t (initially) be??authorizing other??apps/websites/etc. (i.e. “clients”) to use their data (resources) – so the typical??authorization??aspect that you see in many OAuth2 examples (“Application X wants to access??your data – Accept / Deny?”) didn’t apply. Basically, I just wanted a typical login (i.e. cookies) system for round trips to the API, but without the cookie – i.e. with JWTs!

Note that I use Entity Framework and SQL Server for data access/storage, and I’ll be using ASP.NET Identity v3.

First I needed to choose which existing software to use to generate the JWT tokens. Previously, in ASP.NET4, I had used an OWIN implementation that I based on the fantastic??blog of Taiseer Joudeh – at It involved quite a lot of coding so I was hoping for something in v5 that had??less heavy lifting.

I looked at Identity Server v3 first, and got reasonably far, but it also got??quite tricky to understand, as you have to look at an example for using??Identity, and then another example for Entity Framework, and then another example for ASP.NET5, and then another example for JWT tokens, etc – and then try pull them all together. I gave up when I read something about Entity Framework 7 not yet being fully (natively?) supported.

The other??option I was reading about was AspNet.Security.OpenIdConnect.Server (ASOS). But again, this looked quite tricky to pull together. then I stumbled onto the lesser known OpenIddict??software, which is based on ASOS, but??does most of the heavy lifting for you. This is what I ended up choosing.

There are installation instructions on the OpenIddict home page. Note that at the time of writing, you have to use RC2 builds, so you’ll need to run:

You also have to create a??Nuget.Config file in the root of your application, with the following contents:

At the time of writing, these installation instructions mirror what’s on the OpenIddict home page. From here on we’ll start to deviate, though, as we don’t want the default configuration, which seems to be more about authorizing other applications/clients.

First up, we add??hosting.json to the project with the following contents:

My project name is??openiddict-test, so in project.json we set the following commands:

Note that the??web command is the project name, not the namespace name (I originally had it as openiddicttest and the damned thing wouldn’t start).

The new static void main syntax in Startup.cs??is now as follows:

In the config file (in my case, in appsettings.json), we have the database connection string and some logging settings:

Lastly (before we get into the real code), in??project.json, make sure you have the following dependencies:

We don’t actually need the whole of??OpenIddict, we just need the??core for generating the tokens, and the??EF for the entity??Entity Framework aspects, so I’ve just included these two, although you could include the main package if you like. We’re also going to be using the Microsoft JwtBearer package for validating the tokens, so include that now too. Notice that all dependencies are using the “-*” versioning option.

The Real Code

This is where it starts to get interesting.

First we need the User model, so this is the??ApplicationUser.cs file:

Note that we’re deriving from??IdentityUser as you normally would if using ASP.NET Identity. We’re also adding a custom field called??GivenName, which we will include in the JWT token.

Similarly, here is the very simple ApplicationRole.cs file:

It simply derives from??IdentityRole.

Then??we need a??DbContext, so the below is from a file ApplicationDbContext.cs:

Note that we’re deriving from??OpenIddictContext and we’re using an override with 4 parameters: the ApplicationUser, the Application class, the ApplicationRole, and string.??Although we’re not going to be using the Application class, we still need??to use this signature otherwise the roles won’t get populated in the JWT token.

Now, here is the??ConfigureServices method from the Startup.cs:

  • Lines 4-7 are standard for building the configuration options.
  • Lines 10-13 adds??Entity Framework and configures the connection string from the configuration file.
  • Lines 16-19 adds??Identity. Notice Line 19 being the first OpenIddict line of code, which also tells OpenIddict to use Entity Framework.
  • Line 22 adds MVC, for the API.
  • Line 25 adds the Database Initializer, which is simply to seed the database with some data.
  • Line 26 adds a??Custom OpenIddict Manager. The OpenIddict Manager will override the token generation method so we can add the custom field (GivenName) to the JWT token.

Let’s look at the CustomOpenIddictManager.cs:

This??class simply inherits from??OpenIddict.OpenIddictManager<ApplicationUser, Application> and then overrides??CreateIdentityAsyncCreateIdentityAsync. It creates the??claimsIdentity from the base method, and then adds the Given Name claim to the claimsIdentity, and sets the destination property of the claim to both??id_token and token. This simply means that when the token is requested, the Given Name claim should be returned in the token.

Back in the Startup.cs file, we now look at the??Configure method:

  • Lines 3-5 set up logging.
  • Line 7 has??something to do with IIS, I won’t pretend to know what.
  • Line 11 & 10 allow static files to be served (index.html) and lets the index.html page be served as the default page (index.html will be our test??javascript page).
  • Note we??don’t use the identity line on line 14 as this is just a wrapper for cookies.
  • Lines 16-23 configures OpenIddictCore – telling it to use JWT tokens, to allow non-HTTPS requests, and to display errors (these last two??are obviously development settings).
  • Lines 26-33 configures the JWT middleware that will validate the token and thus ensure that the??Authorize attribute on our WebApi methods is??honoured. Note that the audience and authority are the same, but more importantly the??audience must match the??resource value sent in the token request payload (on the index.html page, which we will see later). Also note that you will have to put in the correct values??for your environment here and on index.html, and that this should ideally be stored in the config file.
  • Lines 36-41 configures MVC.
  • Line 44 seeds the database.

I’m not going to cover the Database Initialiser as that just seeds the database with a user and a role. You can view the source on Github if you’re interested.

The??API??endpoint we will be calling to test the token is in??TestController.cs:

This is a pretty standard controller, with these notes:

  • On line 8 we are using the??Authorize attribute to ensure that only authorized (logged in) users can access this data.
  • On line 9 we’re inherting from the MVC Controller class.
  • On lines 11-18 we’re instantiating the controller object, using Dependency Injection to get the??ApplicationDbContext and the??UserManager, which we store in local properties.
  • Line 20??specifies the Route (api/test) and that it’s a??GET request.
  • Line 23-26 gets the user that is logged in. If there’s no user ??it returns a simple text message (there always will be a user??if the??Authorize??attribute is in place on line 7, but you can remove the attribute and call the??url to test it’s working). If there is a user, the user object gets returned.

Basically, this API url??(http://localhost:58292/api/test) will return the user if??logged in, or it will return 401 (Unauthorized).

That is really all there is to it, on the server side.

Client Side Testing Code

This post is not meant to cover what happens on the client side – it could be an AngularJS??website, or a mobile app, or whatever. But to??test that the server is working, below is??the??index.html test page:

  • ??Lines 9-21 are the??form fields for logging in, and the buttons for logging in (getting the token) and getting the api data (using the token).
  • Lines 22-27 are the??outputs of the results of the two button clicks.
  • Lines 29-32 sets up the base url and the button click event handlers.
  • Lines 58-104 gets the token (logs the user in). It basically creates an??XMLHttpRequest that when loaded, will output the token to the controls in lines 22-27. You can ignore the client_id and client_secret lines. Note that the url being called is the base url plus??connect/token. Note the??grant_type, the??resource??(which, as mentioned ealier, must match the settings in Startup.cs), and the scope (offline_access is required to get the refresh??token).
  • Lines 34-56 access the API url. It creates an??XMLHttpRequest that will log the results to the controls in lines 22-27. The API url is simply the base url plus??api/test. Note that the access token is sent as a Bearer token (“Bearer ” + access_token) ??in the Authorization header.
  • Lines 106-132 simply decode the token so the contents can be shown on the page.

If all goes well, you should see the result of the token request (login) and the data request (api call) as shown in the screenshot below.

The code is at Github:??

Good luck!



I must??thank Kevin Chalet, aka Pinpoint / PinPointTownes??for all his assistance. Kevin is the author of OpenIddict and had endless patience with me while I was fumbling my way around.


  1. Sean — Thank your this posting. My frustration with IdentityServer also led me to the OpenIddict project. No disrespect to the IS team and their excellent product, but I was having difficulty as well, knitting together a working solution from the IS samples. It is a little encouraging to hear that I am not alone.

    1. Yep, IS3 seems like a really good tool if you can get it to do what you want it to. But it also seemed like overkill for me and my little web application. I just needed a short way to get from A to B, and OpenIddict fitted that bill quite nicely.

  2. Thank you so very much for this! I wasted my whole summer trying to stitch together sample code from various identity server examples (none of which matched my complete scenario) of an MVC/API along with identity in the back end, using entity framework with SQL server as the data layer, to anthenticate an angular front end app with JWT tokens. I never imagined that WebAPI + JWT + Angular authentication would be so bloody difficult for a concept that is so very simple. Whereas I thought that there would be 10,000 blog posts on that topic, there are sadly very few, so your post is a very welcomed sight, so thank you!

    1. Hi Mike.

      Sounds like you and I had a very similar experience. I also thought it should be simple, coming from a normal cookies background in WebForms where a few web.config lines sets it up and then a couple of lines on the login page are all you need. I also couldn’t believe how difficult it seemed to be and how little info there was out there (hence the motivation to write something).

      I appreciate that these days there are so many different models of authorization – hence the various Flows in OAuth2 – that authorization software has become complex. But if it isn’t comparably easy to set up the “old style authentication” – I think people are just going to walk on by. I think that’s where OpenIddict is getting it right – making sure it’s just a handful of lines to get you off the ground.

      Glad you found it useful!

  3. Thanks for the very useful article!
    Work like a charm)
    A small adjustment – method IActionResult Get() should look like, as
    [Route(“api/test”), HttpGet]
    public async Task Get()
    var user = await _userManager.FindByIdAsync(User.GetUserId());
    if (user == null) return Ok(“No user / not logged in”);// if Authorize is not applied
    return Ok(user);

    1. Hi Serge

      Obviously some sort of character filtering.

      public async Task<IActionResult> Get()

      Hope that comes out right…

  4. Capesean,
    thanks for your beautiful work. Still, I have problems to execute your sample code. For example, I don’t see the Nuget.config file you mention in the article.
    Moreover, if I start from scratch with an ASP.NET 5 Web Api solution, I don’t have the choice to request ‘individual user account authentication’, as it is written on the OpenIddict web site (but this is surely not your fault! :-)).
    Finally, if I start your sample code, I get an untraceable 500 error on ‘connect/token’.
    Please, could you help me in executing correctly your very interesting sample?
    Thanks in advance

    1. Hi Andrea

      The Nuget.Config file is there, see:

      The github repo was updated last night, so if you cloned it before then, it had a few bugs. Should be 100% now, though.

      You don’t actually need any user account authentication – you can start with a blank website with No Authentication, the steps in the blog will add the necessary bits.

      For the 500 error:
      1. Check in Developer Tools if there is any message returned from the request, that might give a clue as to what’s going wront.
      2. The update last night added some logging (see: So run (debug) your website in Visual Studio and after the 500 error, check your Output window to see what the error says. This should also give you an idea of the error.

      Let me know if you’re still stuck.


      1. Sean,
        you are really kind: it was only a problem of SQL Server authentication, changing the connection to my SQL Server Express solved the problem.
        I owe a beer, if you happen to come to Italy! ????
        And now I have to study all of your code, but you really made a good work! Thanks!

  5. great work !! thanks. when I add openiddictcore and openiddictEF references to PROJECT JSON – they could not be resolved. I have RC2 – by default. I have nucget.config in the rool folder

    1. OpenIddict.Core and .EF are on the asp-net contrib feed on myget, so if they can’t be resolved then your nuget.config (check the spelling – you said nucget.config) is problematic. Note that it should be in the root directory of the solution, i.e. at the level of the src folder. NOT at the project level root, i.e. at the project.json level.

  6. Why exactly are the audience and authority similar? Is it because the client and the server are in the same project? I’m assuming the audience represents the client’s project. (I’m still trying to understand some of the concepts)

    1. Hi Greg

      The audience must match the resource sent in the JSON payload. This is effectively the “client” that is using the token. The authority is the url of the authorization server, so in this case, yes, it’s the same. It gets used to access various end-points that help with discovery, e.g. if you try http://localhost:5000/.well-known/jwks (assuming your site is on localhost:5000) then you’ll see some authorisation info used by the OpenIddict software.

  7. One last question. When using this approach, are the refresh tokens persisted in the database as well for easy revocation by admins?

    1. At the moment, revoking refresh tokens is not supported, as they are not persisted. OpenIddict plans to add this in the near future, but it’s not possible currently. The security stamp of a token involves the username and password, so as a (temporary) workaround, you could change/blank the user’s password and that would effectively void any existing refresh tokens.

  8. This is great post!
    One question, after I tried code today, get token works fine.
    However getapidata does not hit test api at all. I also tried hit localhost:58292/api/test directly, no luck to hit breakpoint. it returns index.html page back with 200.
    Any idea?

    1. Sorry Tony. The recent changes made for the Angular login messed that up. The github repo is fixed now – small change in web.config

      1. Thank you!
        One more question, you mentioned you don’t want default config from OpenIddict because you don’t need auth multiple clients. But I didn’t see which step is specific for customized configuration for OpenIddict for this purpose. Could you explain a little bit on that?
        Thanks again.

  9. Sorry keep asking questions.
    After look into this more, there are two more questions come up.
    1. In github source code, for new claim with given name, we add property like this claim.Properties.Add(“destination”, “profile”); It doesn’t work.
    In the post, it uses claim.Properties.Add(“destination”, “id_token token”); It works.
    What makes the difference? Those literal string confused me.
    2. When client making request with scope offline_access in index.html, there is a comment saying it “indicate refresh token is required”. Could you explain this comment? Also, is this project all about refresh token? In real implementation, are we suppose to use this refresh token only to exchange access token? I am asking this because I thought the token in this project was access token, until I saw that comment.
    Thanks for the patience.

    1. Hi Tony

      1. You are right, it should be “id_token token”. It’s basically specifying that the claim should be returned in the token. Ignore the “profile”.

      2. If you don’t include the “offline_access” scope, you won’t get back a refresh token. Try removing it and you will see you don’t get a refresh token in the Token Response. Once you have the refresh token, you can exchange it for a new access token by POSTing it to the same Url (connect/token) with the payload:
      “grant_type=refresh_token&refresh_token=” + refreshToken

  10. Hi, Sean!
    I’ve question about using attribute [Authorize(Roles = “User”)] for Get() method in TestController.
    I tried the following options:

    1) Create role and assign it to user in Seed() method:
    await _roleManager.CreateAsync(new ApplicationRole { Name = “User” });
    await _userManager.AddToRoleAsync(user, “User”);
    Does not work – API Response 403 (forbidden).

    2) Create claim:
    await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Role, “User”));
    The result is the same – API Response 403.

    3) For testing purposes I added this code in CreateIdentityAsync method of CustomOpenIddictManager class:
    claim = new Claim(ClaimTypes.Role, “User”);
    claim.Properties.Add(“destination”, “id_token token”);
    It’s work! – API Response 200

    How to do it correctly?

    1. Hi Serge

      I’ve just updated the Github repo to include adding a role during seeding, and to validate that role in the Authorise attribute. It works fine without your steps (2) & (3). You should also be able to inspect the token, as shown in the last image above, and see the role in the payload, i.e.:


      1. Hi, Sean! Thank you for very quick answer!
        Your example works fine, but if I add another user:
        email = “”;
        if (await _userManager.FindByEmailAsync(email) == null)
        user = new ApplicationUser
        UserName = email,
        Email = email,
        EmailConfirmed = true,
        GivenName = “Admin”
        await _userManager.CreateAsync(user, “P2ssw0rd!”);
        user = await _userManager.FindByEmailAsync(email);
        roleName = “Admin”;
        if (!_context.Roles.Any(r => r.Name.ToLower() == roleName))
        _context.Roles.Add(new ApplicationRole() { Name = roleName });

        if (!await _userManager.IsInRoleAsync(user, roleName))
        await _userManager.AddToRoleAsync(user, roleName);
        In each of the tables AspNetUsers, AspNetRoles, AspNetUserRoles I get two entries.
        Then I get the following tokens:
        for :
        No roles!
        I do not understand what the problem is. Help me, please)

        1. Hi Serge

          OpenIddict was recently modified so you have to specify “roles” as a parameter in the scope of your JSON payload, else you won’t get the roles back in the JWT. I’ve updated my repo to reflect this, you’ll need to do the same for yours.


  11. Great example thank you. Just ran the code and I get a 403 from “testrole”. When I comment out [Authorize(Roles = “testrole”)], I don’t see the role int he payload.

    1. OpenIddict was recently updated so that you have to specify the “roles” as a scope in the JSON payload. I’ve fixed my repo to reflect this, should work now.

  12. Any idea why I would be getting this error when I try to post to connect/token?

    System.TypeLoadException: Could not load type ‘Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider’ from assembly ‘Microsoft.IdentityModel.Tokens, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.
    at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning (Microsoft.IdentityModel.Tokens.SecurityKey key, System.String algorithm) [0x00000] in :0

    1. Not really sure. Have you checked the Output window – does that give any more info? Are your packages all the latest/same versions? Try running dru restore –no-cache. Your OpenIddict.Core package should be version 0127 and the dependent package of AspNet.Security.OpenIdConnect.Server should be 0589. In global.json I’m on sdk version 1.0.0-rc2-16357.

  13. Hi Capesean,
    I am trying to a create token just by adding the openiddict.core dll. But I am getting an ambigious error on my startup.cs due to dependency injection.

    Any assistance would be much appreciated.

  14. Hi Capesean,

    This is a very nice application to demonstrate the jwt token using the latest libraries. In the sources, you have used SQL server as database. Can we use MongoDB as the back end database instead of SQL server? Could you please suggest on what kind of changes are expected in the starup.cs file to switch to Mongo DB? I believe OpenIddict.Core is not tied to SQL server. Please confirm.

    Thanks and Best Regards

    1. Hi Suneel

      As far as I understand it, OpenIddict isn’t aware of the data store. It uses Entity Framework and ASP.NET Security. So for example, if you’re using Entity Framework with Mongo, OpenIddict wouldn’t need to know that. But that’s my very limited understanding and I unfortunately can’t help you any more as I have no experience with Mongo at all.


  15. Hi, Sean! Thank you for quick project update!
    Which commands are used to work with EF?
    “dnx ef” or “dotnet ef” do not work.

  16. Hi Sean,

    Your application is quite good example of how to get the JWT tokens using Openiddict. If i need to use these tokens to authorize my resource server APIs, i need to write authentication and authorization filters which utilize the details in the JWT tokens. Could you please suggest me if there is a reference/example on the web on how to use the Authentication and Authorization filters using these tokens.

    Thanks in Advance

    1. Hi Suneel

      The [Authorize] attribute already works with the API endpoints, so you don’t need to write any filters – just use those from Microsoft.AspNet.Authorization.


  17. Hi Sean,

    I am calling the OpenIddict ‘connect/token’ end point to get the tokens from an angularjs application. I need to record the login history/audit information of the users. Do you have any idea on whether OpenIddict does anything related to saving the login history/audit information? or do we need to explicitly record the success and failures of the calls to the ‘connect/token’ endpoint ? Please suggest if you have any clues/suggestions on this?


  18. Great article, but my code won’t compile. The second I add “OpenIddict.Core”: “1.0.0-*”, “OpenIddict.EF”: “1.0.0-*”, to my project.json file, it starts telling me type or namespace could not be found for basically EVERYTHING in my Startup.cs class. It’s giving the error that these packages aren’t compatible with dnx version 5.0. After some research I believe there are bugs in .net core.

      1. Hi Sean, has your project been updated to match everything in core 1.0.0-rc2 packages? I migrated my whole app to use the rc2 stuff and now I can’t get your sample to work. Getting errors to do with openid configuration.

  19. @Sean, using VS 2015 v14.0.25123.00 Update 2 which doesn’t pick up the coreclr runtimes installed (only clr). I would like to test publishing your project to a docker coreclr image. First is have you tried this? And if so then I assume you have used either a Powershell publish or the dotnet cli. Another issue is that the docker images for coreclr are at rc1-update1. These can be updated with the default feeds (hard coded in the dnvm script) to rc1-update2.

  20. Hi Sean,
    I am trying to run the project from the GitHub. I cloned and did ‘dotnet restore’ and when I do ‘dotnet run’ it throws as error,Unhandled Exception: System.Reflection.TargetInvocationException: Exception has
    been thrown by the target of an invocation. —> System.IO.FileNotFoundException
    : The configuration file ‘appsettings.json’ was not found and is not optional.

    But the file does exist. Could you please help!


  21. Thank you very much for this!
    Could you explain please what is use of Applications table in OpenIddict?
    Currently, my Front end (Angularjs) + Back end (Web.API with ASP.NET Core and OpenIddict) work fine on one server. The Front end receives tokens and uses it in requests. The Back end generates tokens and evaluate them. All good, but Applications table does not have any records.


  22. Hey! Nice article.

    I tried to compile your source code from github but I got erros (

    I suppose the lib OpenIddict has changed and your code didn’t.

    Do you have any updated for the sample code?

    My environment info:

    Microsoft Visual Studio Community 2015
    Version 14.0.25123.00 Update 2
    Microsoft .NET Framework
    Version 4.6.01055

    Installed Version: Community

    ASP.NET and Web Tools 2015.1 14.1.20512.0
    ASP.NET Web Frameworks and Tools 2012.2 4.1.41102.0
    ASP.NET Web Frameworks and Tools 2013 5.2.40314.0
    Microsoft .NET Core Tools (Preview 1) 14.1.20512.0
    NuGet Package Manager 3.4.4

    OpenIddict v1.0.0-alpha2-0326

  23. I have not been able to build the latest source in GetHub. There seems to be a compile error :

    The type or namespace name ‘OpenIddictManager’ does not exist in the namespace ‘OpenIddict’ (are you missing an assembly reference?) openiddict-test..NET Framework 4.5.1, openiddict-test..NETCoreApp,Version=v1.0 C:\Projects\openid\openiddict-test-master\src\openiddict-test\Infrastructure\CustomOpenIddictManager.cs 12 Active

  24. Hey sean, I just downloaded your project, restored all the necessary packages but it shows that there is a problem. OpenIddictManager is expecting one type argument. But you are sending two … What shall I do to resolve this ?

  25. Hi and thank you for great tutorial, I have one problem, the code on github doesn’t build.

    Using the generic type ‘OpenIddictTokenManager’ requires 1 type arguments

    is the visual studio build error. + 6more

  26. Thanks for the write up. This has been a tough one for me to solve. When running your app im getting this error:
    Additional information: At least one OAuth2/OpenID Connect flow must be enabled.

  27. same here: “At least one OAuth2/OpenID Connect flow must be enabled”
    maybe it has to do with the newest bits (i’ve installed an kb update to update 3)

  28. Hi, first of all thanks for your project.
    Unfortunately I’m facing some problems since yesterday. Everything worked fine as aspected and explained but suddenly everything I get is an 404 error when calling the tokenEndpoint.
    Debug Log: “OpenIddict.Infrastructure.OpenIddictProvider: Information: The token request validation process was skipped because the client_id parameter was missing or empty.”
    I don’t know why this is happening suddenly when not changing anything to your default project. I tried to run it with a fresh clone from your git but still an 404 error.
    Same when running your compiled project on a server and when openiddict is added to another project. From the openId specs I found that the client_id is mandatory but I can’t explain how it could work before.
    Thanks in advance

  29. Hi Sean, thanks for taking the time to write this useful article.
    I’m starting with authentication in .net core and it is not easy to understand all these stuff.
    I would like to know if is it possible to customize the default user interface and features that a scaffolded Identity project generates to use JWT tokens instead of cookies. This way I can reuse all that functionality like account creating, signin, double verification, etc.
    I’m considering to have three different projects, authentication project (which renders the default authentication interfaces provided by Identity framework), Api (restful services) and a web project which provides an angular web client.

    I only need to know if it is a matter of replacing the CookieAuthentication section from ConfigureServices at Startup.cs or If this interface is tightly coupled to cookies.

    Thanks! ????

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.