├── .gitignore ├── .nuget ├── NuGet.Config └── NuGet.targets ├── MinimalOwinWebApiSelfHost.sln ├── MinimalOwinWebApiSelfHost ├── App.config ├── Controllers │ └── CompaniesController.cs ├── MinimalOwinWebApiSelfHost.csproj ├── Models │ ├── ApplicationDbContext.cs │ ├── AuthModels.cs │ └── Company.cs ├── OAuthServerProvider │ └── ApplicationOAuthServerProvider.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Startup.cs └── packages.config └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | *.obj 3 | *.exe 4 | *.pdb 5 | *.user 6 | *.aps 7 | *.pch 8 | *.vspscc 9 | *_i.c 10 | *_p.c 11 | *.ncb 12 | *.suo 13 | *.sln.docstates 14 | *.tlb 15 | *.tlh 16 | *.bak 17 | *.cache 18 | *.ilk 19 | *.log 20 | [Bb]in 21 | [Dd]ebug*/ 22 | *.lib 23 | *.sbr 24 | obj/ 25 | [Rr]elease*/ 26 | _ReSharper*/ 27 | [Tt]est[Rr]esult* 28 | *.vssscc 29 | $tf*/ 30 | packages*/ -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | 32 | 33 | 34 | 35 | $(SolutionDir).nuget 36 | 37 | 38 | 39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config 40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config 41 | 42 | 43 | 44 | $(MSBuildProjectDirectory)\packages.config 45 | $(PackagesProjectConfig) 46 | 47 | 48 | 49 | 50 | $(NuGetToolsPath)\NuGet.exe 51 | @(PackageSource) 52 | 53 | "$(NuGetExePath)" 54 | mono --runtime=v4.0.30319 "$(NuGetExePath)" 55 | 56 | $(TargetDir.Trim('\\')) 57 | 58 | -RequireConsent 59 | -NonInteractive 60 | 61 | "$(SolutionDir) " 62 | "$(SolutionDir)" 63 | 64 | 65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) 66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 67 | 68 | 69 | 70 | RestorePackages; 71 | $(BuildDependsOn); 72 | 73 | 74 | 75 | 76 | $(BuildDependsOn); 77 | BuildPackage; 78 | 79 | 80 | 81 | 82 | 83 | 84 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalOwinWebApiSelfHost", "MinimalOwinWebApiSelfHost\MinimalOwinWebApiSelfHost.csproj", "{8CB280DB-41B5-4786-AEFB-1308A1859493}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{AC43AE7A-9ACE-4C19-B96F-E62266AD519B}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {8CB280DB-41B5-4786-AEFB-1308A1859493}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {8CB280DB-41B5-4786-AEFB-1308A1859493}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {8CB280DB-41B5-4786-AEFB-1308A1859493}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {8CB280DB-41B5-4786-AEFB-1308A1859493}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Controllers/CompaniesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Web.Http; 7 | using System.Net.Http; 8 | using MinimalOwinWebApiSelfHost.Models; 9 | 10 | // Add these usings: 11 | using System.Data.Entity; 12 | 13 | namespace MinimalOwinWebApiSelfHost.Controllers 14 | { 15 | [Authorize(Roles="Admin")] 16 | public class CompaniesController : ApiController 17 | { 18 | ApplicationDbContext dbContext = new ApplicationDbContext(); 19 | 20 | public IEnumerable Get() 21 | { 22 | return dbContext.Companies; 23 | } 24 | 25 | 26 | public async Task Get(int id) 27 | { 28 | var company = await dbContext.Companies.FirstOrDefaultAsync(c => c.Id == id); 29 | if (company == null) 30 | { 31 | throw new HttpResponseException( 32 | System.Net.HttpStatusCode.NotFound); 33 | } 34 | return company; 35 | } 36 | 37 | 38 | public async Task Post(Company company) 39 | { 40 | if (company == null) 41 | { 42 | return BadRequest("Argument Null"); 43 | } 44 | var companyExists = await dbContext.Companies.AnyAsync(c => c.Id == company.Id); 45 | 46 | if (companyExists) 47 | { 48 | return BadRequest("Exists"); 49 | } 50 | 51 | dbContext.Companies.Add(company); 52 | await dbContext.SaveChangesAsync(); 53 | return Ok(); 54 | } 55 | 56 | 57 | public async Task Put(Company company) 58 | { 59 | if (company == null) 60 | { 61 | return BadRequest("Argument Null"); 62 | } 63 | var existing = await dbContext.Companies.FirstOrDefaultAsync(c => c.Id == company.Id); 64 | 65 | if (existing == null) 66 | { 67 | return NotFound(); 68 | } 69 | 70 | existing.Name = company.Name; 71 | await dbContext.SaveChangesAsync(); 72 | return Ok(); 73 | } 74 | 75 | 76 | public async Task Delete(int id) 77 | { 78 | var company = await dbContext.Companies.FirstOrDefaultAsync(c => c.Id == id); 79 | if (company == null) 80 | { 81 | return NotFound(); 82 | } 83 | dbContext.Companies.Remove(company); 84 | await dbContext.SaveChangesAsync(); 85 | return Ok(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/MinimalOwinWebApiSelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8CB280DB-41B5-4786-AEFB-1308A1859493} 8 | Exe 9 | Properties 10 | MinimalOwinWebApiSelfHost 11 | MinimalOwinWebApiSelfHost 12 | v4.5 13 | 512 14 | ..\ 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\packages\EntityFramework.6.1.2\lib\net45\EntityFramework.dll 39 | 40 | 41 | ..\packages\EntityFramework.6.1.2\lib\net45\EntityFramework.SqlServer.dll 42 | 43 | 44 | ..\packages\EntityFramework.SqlServerCompact.6.1.2\lib\net45\EntityFramework.SqlServerCompact.dll 45 | 46 | 47 | ..\packages\Microsoft.AspNet.Identity.Core.2.2.0-alpha1\lib\net45\Microsoft.AspNet.Identity.Core.dll 48 | 49 | 50 | ..\packages\Microsoft.AspNet.Identity.EntityFramework.2.1.0\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll 51 | 52 | 53 | ..\packages\Microsoft.AspNet.Identity.Owin.2.2.0-alpha1\lib\net45\Microsoft.AspNet.Identity.Owin.dll 54 | 55 | 56 | False 57 | ..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll 58 | 59 | 60 | ..\packages\Microsoft.Owin.Host.HttpListener.2.0.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll 61 | 62 | 63 | ..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll 64 | 65 | 66 | ..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll 67 | 68 | 69 | ..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll 70 | 71 | 72 | ..\packages\Microsoft.Owin.Security.OAuth.2.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll 73 | 74 | 75 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 76 | 77 | 78 | ..\packages\Owin.1.0\lib\net40\Owin.dll 79 | 80 | 81 | 82 | 83 | 84 | True 85 | ..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll 86 | 87 | 88 | 89 | False 90 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3-beta1\lib\net45\System.Net.Http.Formatting.dll 91 | 92 | 93 | False 94 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3-beta1\lib\net45\System.Web.Http.dll 95 | 96 | 97 | ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3-beta1\lib\net45\System.Web.Http.Owin.dll 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Designer 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 127 | 128 | 129 | 130 | 131 | 132 | if not exist "$(TargetDir)x86" md "$(TargetDir)x86" 133 | xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" 134 | if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" 135 | xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" 136 | 137 | 144 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Models/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | // Add using: 8 | using System.Data.Entity; 9 | using System.Security.Claims; 10 | 11 | namespace MinimalOwinWebApiSelfHost.Models 12 | { 13 | public class ApplicationDbContext : DbContext 14 | { 15 | public ApplicationDbContext() 16 | : base("MyDatabase") 17 | { 18 | 19 | } 20 | 21 | static ApplicationDbContext() 22 | { 23 | Database.SetInitializer(new ApplicationDbInitializer()); 24 | } 25 | 26 | public IDbSet Companies { get; set; } 27 | public IDbSet Users { get; set; } 28 | public IDbSet Claims { get; set; } 29 | } 30 | 31 | 32 | public class ApplicationDbInitializer 33 | : DropCreateDatabaseAlways 34 | { 35 | protected async override void Seed(ApplicationDbContext context) 36 | { 37 | context.Companies.Add(new Company { Name = "Microsoft" }); 38 | context.Companies.Add(new Company { Name = "Apple" }); 39 | context.Companies.Add(new Company { Name = "Google" }); 40 | context.SaveChanges(); 41 | 42 | // Set up two initial users with different role claims: 43 | var john = new MyUser { Email = "john@example.com" }; 44 | var jimi = new MyUser { Email = "jimi@Example.com" }; 45 | 46 | john.Claims.Add(new MyUserClaim { ClaimType = ClaimTypes.Name, UserId = john.Id, ClaimValue = john.Email }); 47 | john.Claims.Add(new MyUserClaim { ClaimType = ClaimTypes.Role, UserId = john.Id, ClaimValue = "Admin" }); 48 | 49 | jimi.Claims.Add(new MyUserClaim { ClaimType = ClaimTypes.Name, UserId = jimi.Id, ClaimValue = jimi.Email }); 50 | jimi.Claims.Add(new MyUserClaim { ClaimType = ClaimTypes.Role, UserId = john.Id, ClaimValue = "User" }); 51 | 52 | var store = new MyUserStore(context); 53 | await store.AddUserAsync(john, "JohnsPassword"); 54 | await store.AddUserAsync(jimi, "JimisPassword"); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Models/AuthModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | // Add usings: 8 | using System.Data.Entity; 9 | using System.ComponentModel.DataAnnotations; 10 | using System.Security.Claims; 11 | 12 | namespace MinimalOwinWebApiSelfHost.Models 13 | { 14 | public class MyUser 15 | { 16 | public MyUser() 17 | { 18 | Id = Guid.NewGuid().ToString(); 19 | Claims = new List(); 20 | } 21 | 22 | [Key] 23 | public string Id { get; set; } 24 | public string Email { get; set; } 25 | public string PasswordHash { get; set; } 26 | public ICollection Claims { get; set; } 27 | } 28 | 29 | 30 | public class MyUserClaim 31 | { 32 | public MyUserClaim() 33 | { 34 | Id = Guid.NewGuid().ToString(); 35 | } 36 | [Key] 37 | public string Id { get; set; } 38 | public string UserId { get; set; } 39 | public string ClaimType { get; set; } 40 | public string ClaimValue { get; set; } 41 | } 42 | 43 | 44 | public class MyPasswordHasher 45 | { 46 | public string CreateHash(string password) 47 | { 48 | // FOR DEMO ONLY! Use a standard method or 49 | // crypto library to do this for real: 50 | char[] chars = password.ToArray(); 51 | char[] hash = chars.Reverse().ToArray(); 52 | return new string(hash); 53 | } 54 | } 55 | 56 | 57 | public class MyUserStore 58 | { 59 | ApplicationDbContext _db; 60 | public MyUserStore(ApplicationDbContext context) 61 | { 62 | _db = context; 63 | } 64 | 65 | 66 | public async Task AddUserAsync(MyUser user, string password) 67 | { 68 | if (await UserExists(user)) 69 | { 70 | throw new Exception( 71 | "A user with that Email address already exists"); 72 | } 73 | var hasher = new MyPasswordHasher(); 74 | user.PasswordHash = hasher.CreateHash(password).ToString(); 75 | _db.Users.Add(user); 76 | await _db.SaveChangesAsync(); 77 | } 78 | 79 | 80 | public async Task FindByEmailAsync(string email) 81 | { 82 | var user = _db.Users 83 | .Include(c => c.Claims) 84 | .FirstOrDefaultAsync(u => u.Email == email); 85 | 86 | return await _db.Users 87 | .FirstOrDefaultAsync(u => u.Email == email); 88 | } 89 | 90 | 91 | public async Task FindByIdAsync(string userId) 92 | { 93 | return await _db.Users 94 | .FirstOrDefaultAsync(u => u.Id == userId); 95 | } 96 | 97 | 98 | public async Task UserExists(MyUser user) 99 | { 100 | return await _db.Users 101 | .AnyAsync(u => u.Id == user.Id || u.Email == user.Email); 102 | } 103 | 104 | 105 | public async Task AddClaimAsync(string UserId, MyUserClaim claim) 106 | { 107 | var user = await FindByIdAsync(UserId); 108 | if(user == null) 109 | { 110 | throw new Exception("User does not exist"); 111 | } 112 | user.Claims.Add(claim); 113 | await _db.SaveChangesAsync(); 114 | } 115 | 116 | 117 | public bool PasswordIsValid(MyUser user, string password) 118 | { 119 | var hasher = new MyPasswordHasher(); 120 | var hash = hasher.CreateHash(password); 121 | return hash.Equals(user.PasswordHash); 122 | } 123 | } 124 | 125 | 126 | //public class Role 127 | //{ 128 | // public Role() 129 | // { 130 | // Id = Guid.NewGuid().ToString(); 131 | // } 132 | 133 | // [Key] 134 | // public string Id { get; set; } 135 | // public string Name { get; set; } 136 | // public List Users { get; set; } 137 | //} 138 | 139 | 140 | //public class UserRole 141 | //{ 142 | // public string UserId { get; set; } 143 | // public User User { get; set; } 144 | 145 | // public string RoleId { get; set; } 146 | // public Role Role { get; set; } 147 | //} 148 | 149 | 150 | //public class UserManager 151 | //{ 152 | // UserStore _userStore; 153 | // public UserManager(UserStore userStore) 154 | // { 155 | // _userStore = userStore; 156 | // } 157 | 158 | 159 | // public async Task CreateAsync(User user, string password) 160 | // { 161 | // if(await _userStore.UserExists(user)) 162 | // { 163 | // throw new Exception("A user with that Email address already exists"); 164 | // } 165 | // var hasher = new PasswordHasher(); 166 | // user.PasswordHash = hasher.CreateHash(password); 167 | // await _userStore.AddUserAsync(user); 168 | // } 169 | 170 | 171 | // public async Task AddClaim(string UserId, Claim claim) 172 | // { 173 | // _userStore.AddClaim() 174 | // } 175 | //} 176 | } 177 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Models/Company.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | // Add using: 8 | using System.ComponentModel.DataAnnotations; 9 | 10 | namespace MinimalOwinWebApiSelfHost.Models 11 | { 12 | public class Company 13 | { 14 | // Add Key Attribute: 15 | [Key] 16 | public int Id { get; set; } 17 | public string Name { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/OAuthServerProvider/ApplicationOAuthServerProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | // Add Usings: 8 | using Microsoft.Owin.Security; 9 | using Microsoft.Owin.Security.OAuth; 10 | using System.Security.Claims; 11 | using MinimalOwinWebApiSelfHost.Models; 12 | 13 | 14 | namespace MinimalOwinWebApiSelfHost.OAuthServerProvider 15 | { 16 | public class ApplicationOAuthServerProvider 17 | : OAuthAuthorizationServerProvider 18 | { 19 | public override async Task ValidateClientAuthentication( 20 | OAuthValidateClientAuthenticationContext context) 21 | { 22 | // This call is required... 23 | // but we're not using client authentication, so validate and move on... 24 | await Task.FromResult(context.Validated()); 25 | } 26 | 27 | 28 | public override async Task GrantResourceOwnerCredentials( 29 | OAuthGrantResourceOwnerCredentialsContext context) 30 | { 31 | // Retrieve user from database: 32 | var store = new MyUserStore(new ApplicationDbContext()); 33 | var user = await store.FindByEmailAsync(context.UserName); 34 | 35 | // Validate user/password: 36 | if(user == null || !store.PasswordIsValid(user, context.Password)) 37 | { 38 | context.SetError( 39 | "invalid_grant", "The user name or password is incorrect."); 40 | context.Rejected(); 41 | return; 42 | } 43 | 44 | // Add claims associated with this user to the ClaimsIdentity object: 45 | var identity = new ClaimsIdentity(context.Options.AuthenticationType); 46 | foreach(var userClaim in user.Claims) 47 | { 48 | identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue)); 49 | } 50 | 51 | context.Validated(identity); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | // Add reference to: 8 | using Microsoft.Owin.Hosting; 9 | using System.Data.Entity; 10 | using MinimalOwinWebApiSelfHost.Models; 11 | 12 | namespace MinimalOwinWebApiSelfHost 13 | { 14 | class Program 15 | { 16 | static void Main(string[] args) 17 | { 18 | // Specify the URI to use for the local host: 19 | string baseUri = "http://localhost:8080"; 20 | 21 | Console.WriteLine("Starting web Server..."); 22 | WebApp.Start(baseUri); 23 | Console.WriteLine("Server running at {0} - press Enter to quit. ", baseUri); 24 | Console.ReadLine(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MinimalOwinWebApiSelfHost")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MinimalOwinWebApiSelfHost")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4e5dbf68-a38f-4291-a066-7e6c73c35b7f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // Add the following usings: 4 | using Owin; 5 | using System.Web.Http; 6 | using MinimalOwinWebApiSelfHost.Models; 7 | using MinimalOwinWebApiSelfHost.OAuthServerProvider; 8 | using Microsoft.Owin.Security.OAuth; 9 | using Microsoft.Owin; 10 | 11 | 12 | namespace MinimalOwinWebApiSelfHost 13 | { 14 | public class Startup 15 | { 16 | // This method is required by Katana: 17 | public void Configuration(IAppBuilder app) 18 | { 19 | ConfigureAuth(app); 20 | 21 | var webApiConfiguration = ConfigureWebApi(); 22 | app.UseWebApi(webApiConfiguration); 23 | } 24 | 25 | 26 | private void ConfigureAuth(IAppBuilder app) 27 | { 28 | var OAuthOptions = new OAuthAuthorizationServerOptions 29 | { 30 | TokenEndpointPath = new PathString("/Token"), 31 | Provider = new ApplicationOAuthServerProvider(), 32 | AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 33 | 34 | // Only do this for demo!! 35 | AllowInsecureHttp = true 36 | }; 37 | app.UseOAuthAuthorizationServer(OAuthOptions); 38 | app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 39 | } 40 | 41 | 42 | private HttpConfiguration ConfigureWebApi() 43 | { 44 | var config = new HttpConfiguration(); 45 | config.Routes.MapHttpRoute( 46 | "DefaultApi", 47 | "api/{controller}/{id}", 48 | new { id = RouteParameter.Optional }); 49 | return config; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MinimalOwinWebApiSelfHost/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MinimalOwinWebApiSelfHost 2 | 3 | This repo contains source code for a series of articles. Each article builds upon the work done in the last. In order that the source for each article make sense in the context of the article, I have separated branches relevant to each article. 4 | 5 | * **Branch: Master -** Will always contain all of the changes, and be up to date with the most recent article in the series 6 | 7 | The branches below are both referred to in [ASP.NET Web Api 2.2: Create a Self-Hosted OWIN-Based Web Api from Scratch](http://typecastexception.com/post/2015/01/11/ASPNET-Web-Api-22-Create-a-Self-Hosted-OWIN-Based-Web-Api-from-Scratch.aspx) 8 | 9 | * **Branch: api -** The minimal example implementation of a self-hosted Web Api application using OWIN/Katana 10 | * **Branch: ef -** Extends the example above by adding entity framework and a local, file-based database (SQL CE) 11 | 12 | The next branch, `auth-minimal` is referred to in the post [ASP.NET Web Api: Understanding OWIN/Katana Authentication/Authorization Part I: Concepts](http://typecastexception.com/post/2015/01/19/ASPNET-Web-Api-Understanding-OWINKatana-AuthenticationAuthorization-Part-I-Concepts.aspx) 13 | 14 | * **Branch: auth-minimal -** Adds simplified authentication examples to the previous branches. Identity is not used, and database persistence is not yet implemented for the auth stuff. 15 | 16 | The next branch, auth-db is referred to in the post [ASP.NET Web Api: Understanding OWIN/Katana Authentication/Authorization Part II: Models and Persistence](http://typecastexception.com/post/2015/01/25/ASPNET-Web-Api-Understanding-OWINKatana-AuthenticationAuthorization-Part-II-Models-and-Persistence.aspx) 17 | 18 | * **Branch: auth-db -** Adds entity models and database persistence. 19 | * 20 | 21 | The Final Branch, `auth-identity` is referred to in the post [ASP.NET Web API: Understanding OWIN/Katana Authentication/Authorization Part III: Adding Identity](http://typecastexception.com/post/2015/02/15/ASPNET-Web-API-Understanding-OWINKatana-AuthenticationAuthorization-Part-III-Adding-Identity.aspx) 22 | 23 | * **Branch: auth-identity ** Replace bare-bones roll-our-own implementation with a minimal Identity framework implementation. 24 | 25 | 26 | --------------------------------------------------------------------------------