├── Images ├── mongodb.png ├── postmanok.png ├── postmantoken.png └── postmanUnauthorized.png ├── .gitignore ├── Controllers ├── IHttpActionResult.cs ├── AuthController.cs └── ProductController.cs ├── Model ├── Settings.cs ├── User.cs └── Product.cs ├── rest.csproj.user ├── Infra ├── JwtSecurityKey.cs ├── JwtToken.cs ├── NoCacheAttribute.cs └── JwtTokenBuilder.cs ├── Repository ├── Interface │ ├── IAuthRepository.cs │ └── IProductRepository.cs ├── AuthRepository.cs └── ProductRepository.cs ├── appsettings.Development.json ├── appsettings.json ├── rest.csproj ├── Program.cs ├── Properties └── launchSettings.json ├── Context ├── AuthContext.cs └── ProductContext.cs ├── README.md └── Startup.cs /Images/mongodb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabioono25/webapicore2jwt/HEAD/Images/mongodb.png -------------------------------------------------------------------------------- /Images/postmanok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabioono25/webapicore2jwt/HEAD/Images/postmanok.png -------------------------------------------------------------------------------- /Images/postmantoken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabioono25/webapicore2jwt/HEAD/Images/postmantoken.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /obj/ 3 | /.vs/ 4 | /.vscode/ 5 | /obj 6 | /wwwroot 7 | .vs/config/applicationhost.config -------------------------------------------------------------------------------- /Images/postmanUnauthorized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabioono25/webapicore2jwt/HEAD/Images/postmanUnauthorized.png -------------------------------------------------------------------------------- /Controllers/IHttpActionResult.cs: -------------------------------------------------------------------------------- 1 | namespace rest.Controllers 2 | { 3 | internal interface IHttpActionResult 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Model/Settings.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace rest.Model 3 | { 4 | public class Settings 5 | { 6 | public string ConnectionString; 7 | public string Database; 8 | } 9 | } -------------------------------------------------------------------------------- /rest.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | IIS Express 5 | 6 | -------------------------------------------------------------------------------- /Infra/JwtSecurityKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using Microsoft.IdentityModel.Tokens; 5 | 6 | namespace rest.Infra 7 | { 8 | public static class JwtSecurityKey 9 | { 10 | public static SymmetricSecurityKey Create(string secret) 11 | { 12 | return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Model/User.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using MongoDB.Bson; 5 | using MongoDB.Bson.Serialization.Attributes; 6 | 7 | namespace rest.Model 8 | { 9 | public class User 10 | { 11 | [BsonId] 12 | public ObjectId Id { get; set; } 13 | public string Name { get; set; } 14 | public string Login { get; set; } 15 | public string Password { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Repository/Interface/IAuthRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using MongoDB.Driver; 7 | using rest.Model; 8 | 9 | namespace rest.Repository.Interface 10 | { 11 | public interface IAuthRepository 12 | { 13 | Task> GetUsers(); 14 | 15 | Task GetUser(string login, string password); 16 | } 17 | } -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | }, 10 | "MongoConnection": { 11 | "ConnectionString": "mongodb://localhost:27017", 12 | "Database": "ProductDb" 13 | }, 14 | "Authentication": { 15 | "Issuer": "issuerTest", 16 | "Audience": "bearerTest", 17 | "SecurityKey": "key-value-token-expires" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "Debug": { 5 | "LogLevel": { 6 | "Default": "Warning" 7 | } 8 | }, 9 | "Console": { 10 | "LogLevel": { 11 | "Default": "Warning" 12 | } 13 | }, 14 | "MongoConnection": { 15 | "ConnectionString": "mongodb://localhost:27017", 16 | "Database": "ProductDb" 17 | }, 18 | "Authentication": { 19 | "Issuer": "issuerTest", 20 | "Audience": "bearerTest", 21 | "SecurityKey": "key-value-token-expires" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Infra/JwtToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IdentityModel.Tokens.Jwt; 3 | using System.Text; 4 | using Microsoft.AspNetCore.Mvc.Filters; 5 | using Microsoft.IdentityModel.Tokens; 6 | 7 | namespace rest.Infra 8 | { 9 | public sealed class JwtToken 10 | { 11 | private JwtSecurityToken token; 12 | 13 | internal JwtToken(JwtSecurityToken token) 14 | { 15 | this.token = token; 16 | } 17 | 18 | public DateTime ValidTo => token.ValidTo; 19 | public string Value => new JwtSecurityTokenHandler().WriteToken(this.token); 20 | } 21 | } -------------------------------------------------------------------------------- /rest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Model/Product.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using MongoDB.Bson; 5 | using MongoDB.Bson.Serialization.Attributes; 6 | 7 | namespace rest.Model 8 | { 9 | public class Product 10 | { 11 | [BsonId] 12 | public string Id { get; set; } 13 | public string Code { get; set; } 14 | public string Name { get; set; } 15 | public bool Active { get; set; } 16 | public string ImageUrl { get; set; } 17 | public string Description { get; set; } 18 | public DateTime CreatedOn { get; set; } 19 | public DateTime UpdatedOn { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Infra/NoCacheAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | 4 | namespace rest.Infra 5 | { 6 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 7 | public sealed class NoCacheAttribute : ActionFilterAttribute 8 | { 9 | public override void OnResultExecuting(ResultExecutingContext context) 10 | { 11 | context.HttpContext.Response.Headers["Cache-Control"] = "no-cache, no-store, max-age=0"; 12 | context.HttpContext.Response.Headers["Pragma"] = "no-cache"; 13 | context.HttpContext.Response.Headers["Expires"] = "-1"; 14 | 15 | base.OnResultExecuting(context); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace rest 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | BuildWebHost(args).Run(); 18 | } 19 | 20 | public static IWebHost BuildWebHost(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup() 23 | .Build(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:60757/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "rest": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:60764/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Repository/Interface/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using MongoDB.Driver; 7 | using rest.Model; 8 | 9 | namespace rest.Repository.Interface 10 | { 11 | public interface IProductRepository 12 | { 13 | Task> GetAllProducts(); 14 | Task GetProduct(string id); 15 | Task AddProduct(Product item); 16 | Task RemoveProduct(string id); 17 | Task UpdateProduct(string id, Product product); 18 | Task UpdateProductDocument(string id, Product product); 19 | Task RemoveAllProducts(); 20 | } 21 | } -------------------------------------------------------------------------------- /Context/AuthContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Options; 7 | using MongoDB.Driver; 8 | using rest.Model; 9 | 10 | namespace rest.Context 11 | { 12 | public class AuthContext{ 13 | 14 | private readonly IMongoDatabase _database = null; 15 | 16 | public AuthContext(IOptions settings) 17 | { 18 | var client = new MongoClient(settings.Value.ConnectionString); 19 | if (client != null) 20 | _database = client.GetDatabase(settings.Value.Database); 21 | } 22 | 23 | public IMongoCollection Users 24 | { 25 | get 26 | { 27 | return _database.GetCollection("User"); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Context/ProductContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Options; 7 | using MongoDB.Driver; 8 | using rest.Model; 9 | 10 | namespace rest.Context 11 | { 12 | public class ProductContext{ 13 | 14 | private readonly IMongoDatabase _database = null; 15 | 16 | public ProductContext(IOptions settings) 17 | { 18 | var client = new MongoClient(settings.Value.ConnectionString); 19 | if (client != null) 20 | _database = client.GetDatabase(settings.Value.Database); 21 | } 22 | 23 | public IMongoCollection Products 24 | { 25 | get 26 | { 27 | return _database.GetCollection("Product"); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Repository/AuthRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Options; 7 | using MongoDB.Bson; 8 | using MongoDB.Driver; 9 | using rest.Context; 10 | using rest.Model; 11 | using rest.Repository.Interface; 12 | 13 | namespace rest.Repository 14 | { 15 | public class AuthRepository : IAuthRepository 16 | { 17 | private readonly AuthContext _context = null; 18 | 19 | public AuthRepository() 20 | { 21 | } 22 | 23 | public AuthRepository(IOptions settings) 24 | { 25 | _context = new AuthContext(settings); 26 | } 27 | 28 | public async Task> GetUsers() 29 | { 30 | var builder = Builders.Filter; 31 | 32 | return await _context.Users.Find(_ => true).ToListAsync();; 33 | } 34 | 35 | public async Task GetUser(string login, string password){ 36 | 37 | var builder = Builders.Filter; 38 | var filter = builder.Eq("Login", login) & builder.Eq("Password", password); 39 | 40 | return await _context.Users 41 | .Find(filter) 42 | .FirstOrDefaultAsync(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Controllers/AuthController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using MongoDB.Bson; 7 | using Newtonsoft.Json; 8 | using rest.Infra; 9 | using rest.Model; 10 | using rest.Repository.Interface; 11 | 12 | namespace rest.Controllers 13 | { 14 | [Produces("application/json")] 15 | [Route("api/[controller]")] 16 | public class AuthController : Controller, IHttpActionResult 17 | { 18 | private readonly IAuthRepository _AuthRepository; 19 | 20 | public AuthController(IAuthRepository AuthRepository) 21 | { 22 | _AuthRepository = AuthRepository; 23 | } 24 | 25 | // POST api/Auth 26 | [HttpPost] 27 | public async Task Create([FromBody]User user) 28 | { 29 | var usr = await _AuthRepository.GetUser(user.Login, user.Password); 30 | 31 | if (usr != null){ 32 | 33 | var token = new JwtTokenBuilder() 34 | .AddSecurityKey(JwtSecurityKey.Create("key-value-token-expires")) 35 | .AddSubject(user.Login) 36 | .AddIssuer("issuerTest") 37 | .AddAudience("bearerTest") 38 | .AddClaim("MembershipId", "111") 39 | .AddExpiry(1) 40 | .Build(); 41 | 42 | return Ok(token.Value); 43 | 44 | }else 45 | return Unauthorized(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Controllers/ProductController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc; 7 | using MongoDB.Bson; 8 | using Newtonsoft.Json; 9 | using rest.Infra; 10 | using rest.Model; 11 | using rest.Repository.Interface; 12 | 13 | namespace rest.Controllers 14 | { 15 | [Authorize(Policy = "Member")] 16 | [Produces("application/json")] 17 | [Route("api/[controller]")] 18 | public class ProductsController : Controller 19 | { 20 | private readonly IProductRepository _ProductRepository; 21 | 22 | public ProductsController(IProductRepository ProductRepository) 23 | { 24 | _ProductRepository = ProductRepository; 25 | } 26 | 27 | [NoCache] 28 | [HttpGet] 29 | public Task> Get() 30 | { 31 | return GetProductInternal(); 32 | } 33 | 34 | private async Task> GetProductInternal() 35 | { 36 | return await _ProductRepository.GetAllProducts(); 37 | } 38 | 39 | // GET api/Products/5 40 | [HttpGet("{id}")] 41 | public Task Get(string id) 42 | { 43 | return GetProductByIdInternal(id); 44 | } 45 | 46 | private async Task GetProductByIdInternal(string id) 47 | { 48 | return await _ProductRepository.GetProduct(id) ?? new Product(); 49 | } 50 | 51 | // POST api/Products 52 | [HttpPost] 53 | public void Post([FromBody]Product product) 54 | { 55 | _ProductRepository.AddProduct(new Product() 56 | { Id = ObjectId.GenerateNewId().ToString(), 57 | Name = product.Name, 58 | Code = product.Code, 59 | Active = true, 60 | Description = product.Description, 61 | ImageUrl = product.ImageUrl, 62 | CreatedOn = DateTime.Now, 63 | UpdatedOn = DateTime.Now 64 | }); 65 | } 66 | 67 | // PUT api/Products/5 68 | [HttpPut("{id}")] 69 | public void Put(string id, [FromBody]Product product) 70 | { 71 | _ProductRepository.UpdateProductDocument(id, product); 72 | } 73 | 74 | // DELETE api/Products/23243423 75 | [HttpDelete("{id}")] 76 | public void Delete(string id) 77 | { 78 | _ProductRepository.RemoveProduct(id); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Repository/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Options; 7 | using MongoDB.Bson; 8 | using MongoDB.Driver; 9 | using rest.Context; 10 | using rest.Model; 11 | 12 | namespace rest.Repository.Interface 13 | { 14 | public class ProductRepository : IProductRepository 15 | { 16 | private readonly ProductContext _context = null; 17 | 18 | public ProductRepository() 19 | { 20 | } 21 | 22 | public ProductRepository(IOptions settings) 23 | { 24 | _context = new ProductContext(settings); 25 | } 26 | 27 | public async Task AddProduct(Product item) 28 | { 29 | await _context.Products.InsertOneAsync(item); 30 | } 31 | 32 | public async Task> GetAllProducts() 33 | { 34 | return await _context.Products.Find(_ => true).ToListAsync(); 35 | } 36 | 37 | public async Task GetProduct(string id) 38 | { 39 | var filter = Builders.Filter.Eq("Id", id); 40 | return await _context.Products 41 | .Find(filter) 42 | .FirstOrDefaultAsync(); 43 | } 44 | 45 | public async Task RemoveAllProducts() 46 | { 47 | return await _context.Products.DeleteManyAsync(new BsonDocument()); 48 | } 49 | 50 | public async Task RemoveProduct(string id) 51 | { 52 | return await _context.Products.DeleteOneAsync( 53 | Builders.Filter.Eq("Id", id)); 54 | } 55 | 56 | public async Task UpdateProduct(string id, Product item) 57 | { 58 | try 59 | { 60 | return await _context.Products 61 | .ReplaceOneAsync(n => n.Id.Equals(id) 62 | , item 63 | , new UpdateOptions { IsUpsert = true }); 64 | } 65 | catch (Exception ex) 66 | { 67 | // log or manage the exception 68 | throw ex; 69 | } 70 | } 71 | 72 | public async Task UpdateProductDocument(string id, Product product) 73 | { 74 | var item = await GetProduct(id) ?? new Product(); 75 | item.Active = product.Active; 76 | item.Code = product.Code; 77 | item.Name = product.Name; 78 | item.UpdatedOn = DateTime.Now; 79 | 80 | return await UpdateProduct(id, item); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /Infra/JwtTokenBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IdentityModel.Tokens.Jwt; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Text; 7 | using Microsoft.AspNetCore.Mvc.Filters; 8 | using Microsoft.IdentityModel.Tokens; 9 | 10 | namespace rest.Infra 11 | { 12 | public sealed class JwtTokenBuilder 13 | { 14 | private SecurityKey securityKey = null; 15 | private string subject = ""; 16 | private string issuer = ""; 17 | private string audience = ""; 18 | private Dictionary claims = new Dictionary(); 19 | private int expiryInMinutes = 5; 20 | 21 | public JwtTokenBuilder AddSecurityKey(SecurityKey securityKey) 22 | { 23 | this.securityKey = securityKey; 24 | return this; 25 | } 26 | 27 | public JwtTokenBuilder AddSubject(string subject) 28 | { 29 | this.subject = subject; 30 | return this; 31 | } 32 | 33 | public JwtTokenBuilder AddIssuer(string issuer) 34 | { 35 | this.issuer = issuer; 36 | return this; 37 | } 38 | 39 | public JwtTokenBuilder AddAudience(string audience) 40 | { 41 | this.audience = audience; 42 | return this; 43 | } 44 | 45 | public JwtTokenBuilder AddClaim(string type, string value) 46 | { 47 | this.claims.Add(type, value); 48 | return this; 49 | } 50 | 51 | public JwtTokenBuilder AddClaims(Dictionary claims) 52 | { 53 | this.claims.Union(claims); 54 | return this; 55 | } 56 | 57 | public JwtTokenBuilder AddExpiry(int expiryInMinutes) 58 | { 59 | this.expiryInMinutes = expiryInMinutes; 60 | return this; 61 | } 62 | 63 | public JwtToken Build() 64 | { 65 | EnsureArguments(); 66 | 67 | var claims = new List 68 | { 69 | new Claim(JwtRegisteredClaimNames.Sub, this.subject), 70 | new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) 71 | } 72 | .Union(this.claims.Select(item => new Claim(item.Key, item.Value))); 73 | 74 | var token = new JwtSecurityToken( 75 | issuer: this.issuer, 76 | audience: this.audience, 77 | claims: claims, 78 | expires: DateTime.UtcNow.AddMinutes(expiryInMinutes), 79 | signingCredentials: new SigningCredentials( 80 | this.securityKey, 81 | SecurityAlgorithms.HmacSha256)); 82 | 83 | return new JwtToken(token); 84 | } 85 | 86 | #region " private " 87 | 88 | private void EnsureArguments() 89 | { 90 | if (this.securityKey == null) 91 | throw new ArgumentNullException("Security Key"); 92 | 93 | if (string.IsNullOrEmpty(this.subject)) 94 | throw new ArgumentNullException("Subject"); 95 | 96 | if (string.IsNullOrEmpty(this.issuer)) 97 | throw new ArgumentNullException("Issuer"); 98 | 99 | if (string.IsNullOrEmpty(this.audience)) 100 | throw new ArgumentNullException("Audience"); 101 | } 102 | 103 | #endregion 104 | } 105 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example of REST API Using MongoDB, .NET Core 2.0 and JWT Authentication 2 | 3 | ### Technologies: 4 | 5 | - .NET Core 2.0; 6 | - MongoDB; 7 | - JWT Authentication. 8 | 9 | ### Running this solution: 10 | 11 | First download or clone the project in a local directory: 12 | 13 | Then you must create a local or cloud MongoDB instance. In this instance, it's necessary the creation of a **ProductDb** 14 | database and two collections, **Product** and **User**. You can use this commands bellow so you can incluse the user: 15 | 16 | ```javascript 17 | db.User.insert({"Name": "Joao Teste", "Login": "joao", "Password": "1234"}) 18 | ``` 19 | 20 | ![Alt text](https://github.com/fabioono25/webapicore2jwt/blob/master/Images/mongodb.png "MongoDB Configuration") 21 | 22 | It's necessary to configure **appsettings.Development.json** with your instance of MongoDB: 23 | 24 | ```javascript 25 | "ConnectionString": "mongodb://localhost:27017", 26 | ``` 27 | 28 | Next, you can open you project in Visual Studio or Visual Studio Code. You can type these two commands (to restore nuget package components and run the API): 29 | 30 | ```mongodb 31 | dotnet restore 32 | ``` 33 | 34 | ```javascript 35 | dotnet run 36 | ``` 37 | 38 | Now, if everything is all right, your API will be working. You must run the command bellow so you can create as authentication token: 39 | 40 | ```javascript 41 | http://localhost:5000/api/Auth 42 | ``` 43 | 44 | Remember: it's necessary define **user** and **password** in payload: 45 | 46 | ```javascript 47 | { 48 | "Login": "joao", 49 | "Password": "1234" 50 | } 51 | ``` 52 | 53 | The result is like this: 54 | 55 | ![Alt text](https://github.com/fabioono25/webapicore2jwt/blob/master/Images/postmanok.png "Postman Token") 56 | 57 | You must use this token so you can use GET, POST, PUT, DELETE verbs. For every of these REST verbs, you must put the generated token in **Authorization Header**, with the word **Bearer** like this: 58 | 59 | ```javascript 60 | Header: Authorization 61 | Value: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2FvIiwianRpIjoiMTFlYWFlODMtZTA4NS00NjA1LTlhNGQtZWI5ZjEzZjdhMDk5IiwiTWVtYmVyc2hpcElkIjoiMTExIiwiZXhwIjoxNTEwMTk0NjQ5LCJpc3MiOiJpc3N1ZXJUZXN0IiwiYXVkIjoiYmVhcmVyVGVzdCJ9.mN3uPfdK19xeMbOoeFfhtuFSpXrGUZ7eR6muM7Nz_fo 62 | ``` 63 | 64 | To use POST, so you can insert some Products, use this URL bellow: 65 | 66 | ```javascript 67 | http://localhost:5000/api/Products 68 | ``` 69 | 70 | With this payloads: 71 | 72 | ```javascript 73 | { 74 | "Code": "COD1", 75 | "Name": "Produto 1", 76 | "Active": true, 77 | "ImageUrl": "http://download.gamezone.com/uploads/image/data/1102202/League_of_Legends_Rune_Wars_Renekton.jpg", 78 | "Description": "Descrição do Produto 1" 79 | } 80 | ``` 81 | ```javascript 82 | { 83 | "Code": "COD2", 84 | "Name": "Produto 2", 85 | "Active": true, 86 | "ImageUrl": "http://images.nintendolife.com/news/2014/08/weirdness_yoshis_real_name_is_both_silly_and_scientific/attachment/0/900x.jpg", 87 | "Description": "Descrição do Produto 2" 88 | } 89 | ``` 90 | ```javascript 91 | { 92 | "Code": "COD3", 93 | "Name": "Produto 3", 94 | "Active": true, 95 | "ImageUrl": "http://da-v4-mbl.digitalbrandsinc.netdna-cdn.com/wp-content/uploads/2012/08/snails-612x320.jpg", 96 | "Description": "Descrição do Produto 3" 97 | } 98 | ``` 99 | 100 | Now you can list the products inserted. Use this URL: 101 | 102 | ```javascript 103 | https://github.com/fabioono25/webapicore2jwt/blob/master/Images/postmanok.png 104 | ``` 105 | 106 | ![Alt text](https://github.com/fabioono25/webapicore2jwt/blob/master/Images/postmanok.png "Postman Product List") 107 | 108 | 109 | Remember, we are using a JWT Token Authentication. The definition of the expiration is 1 minute. Because of this, you maybe get **Error 401 - Unauthorized**. It's perfectly normal: 110 | 111 | 112 | ![Alt text](https://github.com/fabioono25/webapicore2jwt/blob/master/Images/postmanUnauthorized.png "Postman Product List") 113 | 114 | You just generate another token and put it on Header Authorization. 115 | 116 | 117 | -------------------------------------------------------------------------------- /Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication.JwtBearer; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Logging; 11 | using Microsoft.Extensions.Options; 12 | using Microsoft.IdentityModel.Tokens; 13 | using rest.Infra; 14 | using rest.Model; 15 | using rest.Repository; 16 | using rest.Repository.Interface; 17 | 18 | namespace rest 19 | { 20 | public class Startup 21 | { 22 | public Startup(IConfiguration configuration) 23 | { 24 | Configuration = configuration; 25 | } 26 | 27 | public IConfiguration Configuration { get; } 28 | 29 | // This method gets called by the runtime. Use this method to add services to the container. 30 | public void ConfigureServices(IServiceCollection services) 31 | { 32 | services.AddCors(options => 33 | { 34 | options.AddPolicy("CorsPolicy", 35 | builder => builder.AllowAnyOrigin() 36 | .AllowAnyMethod() 37 | .AllowAnyHeader() 38 | .AllowCredentials()); 39 | }); 40 | 41 | //services.AddCors(); 42 | 43 | services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 44 | .AddJwtBearer(options => { 45 | options.TokenValidationParameters = new TokenValidationParameters 46 | { 47 | ValidateIssuer = true, 48 | ValidateAudience = true, 49 | ValidateLifetime = true, 50 | ValidateIssuerSigningKey = true, 51 | 52 | ValidIssuer = Configuration.GetSection("Authentication:Issuer").Value, 53 | ValidAudience = Configuration.GetSection("Authentication:Audience").Value, 54 | IssuerSigningKey = JwtSecurityKey.Create(Configuration.GetSection("Authentication:SecurityKey").Value) 55 | }; 56 | 57 | options.Events = new JwtBearerEvents 58 | { 59 | OnAuthenticationFailed = context => 60 | { 61 | Console.WriteLine("OnAuthenticationFailed: " + context.Exception.Message); 62 | return Task.CompletedTask; 63 | }, 64 | OnTokenValidated = context => 65 | { 66 | Console.WriteLine("OnTokenValidated: " + context.SecurityToken); 67 | return Task.CompletedTask; 68 | } 69 | }; 70 | }); 71 | 72 | services.AddAuthorization(options => 73 | { 74 | options.AddPolicy("Member", 75 | policy => policy.RequireClaim("MembershipId")); 76 | }); 77 | 78 | services.AddMvc(); 79 | 80 | services.Configure(options => 81 | { 82 | options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value; 83 | options.Database = Configuration.GetSection("MongoConnection:Database").Value; 84 | }); 85 | 86 | services.AddTransient(); 87 | services.AddTransient(); 88 | 89 | } 90 | 91 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 92 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 93 | { 94 | // if (env.IsDevelopment()) 95 | // { 96 | // app.UseDeveloperExceptionPage(); 97 | // } 98 | 99 | app.UseCors("CorsPolicy"); 100 | app.UseDeveloperExceptionPage(); 101 | app.UseStaticFiles(); 102 | app.UseAuthentication(); 103 | app.UseMvcWithDefaultRoute(); 104 | 105 | app.UseMvc(); 106 | } 107 | } 108 | } 109 | --------------------------------------------------------------------------------