├── .gitignore ├── AuthorizationServer.sln ├── AuthorizationServer ├── AuthorizationServer.csproj ├── Controllers │ ├── AuthorizationController.cs │ ├── AuthorizationDecisionController.cs │ ├── BaseController.cs │ ├── ConfigurationController.cs │ ├── IntrospectionController.cs │ ├── JwksController.cs │ ├── RevocationController.cs │ └── TokenController.cs ├── Db │ ├── UserDao.cs │ └── UserEntity.cs ├── Models │ └── AuthorizationPageModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Spi │ ├── AuthorizationRequestDecisionHandlerSpiImpl.cs │ ├── AuthorizationRequestHandlerSpiImpl.cs │ ├── NoInteractionHandlerSpiImpl.cs │ └── TokenRequestHandlerSpiImpl.cs ├── Startup.cs ├── Util │ ├── Renderer.cs │ ├── TData.cs │ └── UserTData.cs ├── Views │ └── Authorization │ │ └── Page.cshtml ├── appsettings.Development.json ├── appsettings.json ├── authlete.properties └── wwwroot │ ├── css │ ├── authorization.css │ └── index.css │ └── index.html ├── CUSTOMIZATION.ja.md ├── CUSTOMIZATION.md ├── LICENSE ├── README.ja.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Autosave files 2 | *~ 3 | *.swp 4 | 5 | # build 6 | [Oo]bj/ 7 | [Bb]in/ 8 | packages/ 9 | TestResults/ 10 | 11 | # globs 12 | Makefile.in 13 | *.DS_Store 14 | *.sln.cache 15 | *.suo 16 | *.cache 17 | *.pidb 18 | *.userprefs 19 | *.usertasks 20 | config.log 21 | config.make 22 | config.status 23 | aclocal.m4 24 | install-sh 25 | autom4te.cache/ 26 | *.user 27 | *.tar.gz 28 | tarballs/ 29 | test-results/ 30 | Thumbs.db 31 | 32 | # Mac bundle stuff 33 | *.dmg 34 | *.app 35 | 36 | # resharper 37 | *_Resharper.* 38 | *.Resharper 39 | 40 | # dotCover 41 | *.dotCover 42 | 43 | # Authlete 44 | local.authlete.properties 45 | -------------------------------------------------------------------------------- /AuthorizationServer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuthorizationServer", "AuthorizationServer\AuthorizationServer.csproj", "{EF44297D-1F76-4AF9-9963-02A8F59546B3}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {EF44297D-1F76-4AF9-9963-02A8F59546B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {EF44297D-1F76-4AF9-9963-02A8F59546B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {EF44297D-1F76-4AF9-9963-02A8F59546B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {EF44297D-1F76-4AF9-9963-02A8F59546B3}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | version = 1.0 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /AuthorizationServer/AuthorizationServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 1.0 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 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/AuthorizationController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Microsoft.AspNetCore.Mvc.ViewEngines; 23 | using Authlete.Api; 24 | using Authlete.Dto; 25 | using Authlete.Handler; 26 | using Authlete.Types; 27 | using Authlete.Util; 28 | using Authlete.Web; 29 | using AuthorizationServer.Models; 30 | using AuthorizationServer.Spi; 31 | using AuthorizationServer.Util; 32 | 33 | 34 | namespace AuthorizationServer.Controllers 35 | { 36 | /// 37 | /// An implementation of OAuth 2.0 38 | /// authorization 39 | /// endpoint with 40 | /// OpenID Connect 41 | /// support. 42 | /// 43 | [Route("api/[controller]")] 44 | public class AuthorizationController : BaseController 45 | { 46 | // View name of the authorization page. See "View discovery" 47 | // of "Views in ASP.NET Core MVC" for details. 48 | const string VIEW_NAME = "Page"; 49 | 50 | 51 | readonly IViewEngine _viewEngine; 52 | 53 | 54 | public AuthorizationController( 55 | IAuthleteApi api, ICompositeViewEngine viewEngine) 56 | : base(api) 57 | { 58 | _viewEngine = viewEngine; 59 | } 60 | 61 | 62 | /// 63 | /// An authorization endpoint for HTTP GET method. 64 | /// 65 | /// 66 | /// 67 | /// 68 | /// 3.1. Authorization Endpoint (RFC 6749) says that the 69 | /// authorization endpoint MUST support GET method. 70 | /// 71 | /// 72 | [HttpGet] 73 | public async Task Get() 74 | { 75 | // Query parameters. 76 | string parameters = Request.QueryString.ToString(); 77 | 78 | return await Process(parameters); 79 | } 80 | 81 | 82 | /// 83 | /// An authorization endpoint for HTTP POST method. 84 | /// 85 | /// 86 | /// 87 | /// 88 | /// 3.1. Authorization Endpoint (RFC 6749) says that the 89 | /// authorization endpoint MAY support POST method. 90 | /// 91 | /// 92 | /// 93 | /// In addition, 3.1.2.1. Authentication Request (OpenID 94 | /// Connect Core 1.0) says that the authorization endpoint 95 | /// MUST support POST method. 96 | /// 97 | /// 98 | [HttpPost] 99 | [Consumes("application/x-www-form-urlencoded")] 100 | public async Task Post() 101 | { 102 | // Form parameters. 103 | string parameters = await ReadRequestBodyAsString(); 104 | 105 | return await Process(parameters); 106 | } 107 | 108 | 109 | async Task Process(string parameters) 110 | { 111 | // Call Authlete's /api/auth/authorization API. 112 | AuthorizationResponse response = 113 | await CallAuthorizationApi(parameters); 114 | 115 | // 'action' in the response denotes the next action 116 | // which this authorization endpoint implementation 117 | // should take. 118 | AuthorizationAction action = response.Action; 119 | 120 | // Dispatch according to the action. 121 | switch (action) 122 | { 123 | case AuthorizationAction.INTERACTION: 124 | // Process the authorization request with 125 | // user interaction. 126 | return await HandleInteraction(response); 127 | 128 | case AuthorizationAction.NO_INTERACTION: 129 | // Process the authorization request without 130 | // user interaction. The flow reaches here 131 | // only when the authorization request contains 132 | // 'prompt=none'. 133 | return await HandleNoInteraction(response); 134 | 135 | default: 136 | // Handle other error cases here. 137 | return HandleError(response); 138 | } 139 | } 140 | 141 | 142 | async Task CallAuthorizationApi( 143 | string parameters) 144 | { 145 | // Create a request for Authlete's 146 | // /api/auth/authorization API. 147 | var request = new AuthorizationRequest 148 | { 149 | Parameters = parameters 150 | }; 151 | 152 | // Call Authlete's /api/auth/authorization API. 153 | return await API.Authorization(request); 154 | } 155 | 156 | 157 | async Task HandleNoInteraction( 158 | AuthorizationResponse response) 159 | { 160 | // Make NoInteractionHandler handle the case of 161 | // 'prompt=none'. An implementation of the 162 | // INoInteractionHandlerSpi interface needs to be given 163 | // to the constructor of NoInteractionHandler. 164 | return await new NoInteractionHandler( 165 | API, new NoInteractionHandlerSpiImpl(this)) 166 | .Handle(response); 167 | } 168 | 169 | 170 | HttpResponseMessage HandleError(AuthorizationResponse response) 171 | { 172 | // Make AuthorizationRequestErrorHandler handle the 173 | // error case. 174 | return new AuthorizationRequestErrorHandler() 175 | .Handle(response); 176 | } 177 | 178 | 179 | async Task HandleInteraction( 180 | AuthorizationResponse response) 181 | { 182 | // Store some variables into TempData so that they can 183 | // be referred to in AuthorizationDecisionController. 184 | var data = new UserTData(TempData); 185 | data.Set( "ticket", response.Ticket); 186 | data.SetObject("claimNames", response.Claims); 187 | data.SetObject("claimLocales", response.ClaimsLocales); 188 | 189 | // Clear user information in TempData if necessary. 190 | ClearUserDataIfNecessary(response, data); 191 | 192 | // Prepare a model object which is needed to render 193 | // the authorization page. 194 | var model = new AuthorizationPageModel( 195 | response, data.GetUserEntity()); 196 | 197 | // Render the authorization page manually. 198 | string html = await Render(VIEW_NAME, model); 199 | 200 | // Return "200 OK" with "text/html". 201 | return ResponseUtility.OkHtml(html); 202 | } 203 | 204 | 205 | void ClearUserDataIfNecessary( 206 | AuthorizationResponse response, UserTData data) 207 | { 208 | // Get the user information from TempData. 209 | var entity = data.GetUserEntity(); 210 | 211 | // If user information does not exist in TempData. 212 | if (entity == null) 213 | { 214 | // Nothing to clear. 215 | return; 216 | } 217 | 218 | // If 'login' is required (= if the "prompt" parameter 219 | // of the authorization request includes "login"). 220 | if (IsLoginRequired(response)) 221 | { 222 | // Even if a user has already logged in, the user 223 | // needs to be re-authenticated. This simple 224 | // implementation forces the user to log out here. 225 | data.RemoveUserTData(); 226 | return; 227 | } 228 | 229 | // If the max authentication age has been exceeded. 230 | if (IsMaxAgeExceeded(response, data)) 231 | { 232 | // Much time has elapsed since the last login, so 233 | // re-authentication is needed. This simple 234 | // implementation forces the user to log out here. 235 | data.RemoveUserTData(); 236 | return; 237 | } 238 | 239 | // No need to clear user data. 240 | } 241 | 242 | 243 | bool IsLoginRequired(AuthorizationResponse response) 244 | { 245 | // If the authorization request does not have 246 | // a "prompt" request parameter. 247 | if (response.Prompts == null) 248 | { 249 | // 'login' is not required. 250 | return false; 251 | } 252 | 253 | // For each value in the "prompt" request parameter. 254 | foreach (Prompt prompt in response.Prompts) 255 | { 256 | if (prompt == Prompt.LOGIN) 257 | { 258 | // 'login' is required. 259 | return true; 260 | } 261 | } 262 | 263 | // 'login' is not required. 264 | return false; 265 | } 266 | 267 | 268 | bool IsMaxAgeExceeded( 269 | AuthorizationResponse response, UserTData data) 270 | { 271 | if (response.MaxAge <= 0) 272 | { 273 | // Don't have to care about the maximum 274 | // authentication age. 275 | return false; 276 | } 277 | 278 | // Calculate the number of seconds that have elapsed 279 | // since the last login. 280 | long age = 281 | TimeUtility.CurrentTimeSeconds() 282 | - data.GetUserAuthenticatedAt(); 283 | 284 | if (age <= response.MaxAge) 285 | { 286 | // The max age is not exceeded yet. 287 | return false; 288 | } 289 | 290 | // The max age has been exceeded. 291 | return true; 292 | } 293 | 294 | 295 | async Task Render(string viewName, object model) 296 | { 297 | // Render the view manually. 298 | return await new Renderer(this, _viewEngine) 299 | .Render(viewName, model); 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/AuthorizationDecisionController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | using Authlete.Util; 25 | using AuthorizationServer.Db; 26 | using AuthorizationServer.Spi; 27 | using AuthorizationServer.Util; 28 | 29 | 30 | namespace AuthorizationServer.Controllers 31 | { 32 | /// 33 | /// The endpoint that receives a request from the form in the 34 | /// authorization page. 35 | /// 36 | [Route("api/authorization/decision")] 37 | public class AuthorizationDecisionController : BaseController 38 | { 39 | public AuthorizationDecisionController(IAuthleteApi api) 40 | : base(api) 41 | { 42 | } 43 | 44 | 45 | [HttpPost] 46 | [Consumes("application/x-www-form-urlencoded")] 47 | public async Task Post() 48 | { 49 | // Wrap TempData. 50 | var data = new UserTData(TempData); 51 | 52 | // Authenticate the user if necessary. 53 | AuthenticateUserIfNecessary(data); 54 | 55 | // Flag which indicates whether the user has given 56 | // authorization to the client application or not. 57 | bool authorized = IsClientAuthorized(); 58 | 59 | // Parameters contained in the authorization request. 60 | string ticket = (string)data.Get("ticket"); 61 | string[] claimNames = data.GetObject("claimNames"); 62 | string[] claimLocales = data.GetObject("claimLocales"); 63 | 64 | // Process the authorization request according to the 65 | // decision made by the user. 66 | return await HandleDecision( 67 | authorized, ticket, claimNames, claimLocales); 68 | } 69 | 70 | 71 | void AuthenticateUserIfNecessary(UserTData data) 72 | { 73 | // If user information is already stored in TempData. 74 | if (data.HasUserEntity()) 75 | { 76 | // Already logged in. No need to authenticate the 77 | // user here again. 78 | return; 79 | } 80 | 81 | // Values input to the form in the authorization page. 82 | string loginId = Request.Form["loginId"]; 83 | string password = Request.Form["password"]; 84 | 85 | // Search the user database for the user. 86 | UserEntity entity = 87 | UserDao.GetByCredentials(loginId, password); 88 | 89 | // If the user was found. 90 | if (entity != null) 91 | { 92 | // The user was authenticated successfully. 93 | data.SetUserEntity(entity); 94 | data.SetUserAuthenticatedAt( 95 | TimeUtility.CurrentTimeSeconds()); 96 | } 97 | } 98 | 99 | 100 | bool IsClientAuthorized() 101 | { 102 | // If the user pressed "Authorize" button, the request 103 | // contains an "authorized" parameter. 104 | return Request.Form.ContainsKey("authorized"); 105 | } 106 | 107 | 108 | async Task HandleDecision( 109 | bool authorized, string ticket, 110 | string[] claimNames, string[] claimLocales) 111 | { 112 | var spi = new AuthorizationRequestDecisionHandlerSpiImpl(this, authorized); 113 | var handler = new AuthorizationRequestDecisionHandler(API, spi); 114 | 115 | return await handler.Handle(ticket, claimNames, claimLocales); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/BaseController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.IO; 20 | using System.Text; 21 | using System.Threading.Tasks; 22 | using Microsoft.AspNetCore.Mvc; 23 | using Microsoft.Extensions.Primitives; 24 | using Authlete.Api; 25 | 26 | 27 | namespace AuthorizationServer.Controllers 28 | { 29 | /// 30 | /// Base controller. 31 | /// 32 | public class BaseController : Controller 33 | { 34 | /// 35 | /// Constructor with an implementation of the 36 | /// IAuthleteApi interface. The given instance can 37 | /// be referred to as the value of the API property. 38 | /// 39 | public BaseController(IAuthleteApi api) 40 | { 41 | API = api; 42 | } 43 | 44 | 45 | /// 46 | /// The implementation of the IAuthleteApi interface 47 | /// that was given to the constructor. 48 | /// 49 | public IAuthleteApi API { get; } 50 | 51 | 52 | /// 53 | /// Read the request body as a string. 54 | /// 55 | public async Task ReadRequestBodyAsString() 56 | { 57 | using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) 58 | { 59 | return await reader.ReadToEndAsync(); 60 | } 61 | } 62 | 63 | 64 | /// 65 | /// Get the value of a request HTTP header. 66 | /// 67 | /// 68 | /// 69 | /// The value of the specified HTTP header in the request. 70 | /// 71 | /// 72 | /// 73 | /// The name of an HTTP header. 74 | /// 75 | public string GetRequestHeaderValue(string headerName) 76 | { 77 | StringValues values = Request.Headers[headerName]; 78 | 79 | // Return the value of the first entry. 80 | return values.GetEnumerator().Current; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/ConfigurationController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | 25 | 26 | namespace AuthorizationServer.Controllers 27 | { 28 | /// 29 | /// An implementation of an OpenID Provider configuration 30 | /// endpoint. 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// An OpenID Provider that supports 36 | /// OpenID 37 | /// Connect Discovery 1.0 must provide an endpoint that 38 | /// returns its configuration information in JSON format. 39 | /// Details about the format are described in 40 | /// 3. 41 | /// OpenID Provider Metadata. 42 | /// 43 | /// 44 | /// 45 | /// Note that the URI of an OpenID Provider configuration 46 | /// endpoint is defined in 47 | /// 4.1. 48 | /// OpenID Provider Configuration Request. In short, the 49 | /// URI must be: 50 | /// 51 | /// 52 | /// 53 | /// Issuer Identifier + /.well-known/openid-configuration 54 | /// 55 | /// 56 | /// 57 | /// Issuer Identifier is a URL to identify an OpenID 58 | /// Provider. For example, https://example.com. For 59 | /// details about Issuer Identifier, see the description of 60 | /// "issuer" in 61 | /// 3. 62 | /// OpenID Provider Metadata (OpenID Connect Discovery 1.0) 63 | /// and the description of "iss" in 64 | /// 2. 65 | /// ID Token (OpenID Connect Core 1.0). 66 | /// 67 | /// 68 | /// 69 | /// You can change the Issuer Identifier of your service using 70 | /// the management console (Serivce Owner Console). Note that 71 | /// the default value of Issuer Identifier is not appropriate 72 | /// for production use, so you should change it. 73 | /// 74 | /// 75 | [Route(".well-known/openid-configuration")] 76 | public class ConfigurationController : BaseController 77 | { 78 | public ConfigurationController(IAuthleteApi api) : base(api) 79 | { 80 | } 81 | 82 | 83 | /// 84 | /// OpenID Provider configuration endpoint. 85 | /// 86 | [HttpGet] 87 | public async Task Get() 88 | { 89 | // Call Authlete's /api/service/configuration API. 90 | return await new ConfigurationRequestHandler(API).Handle(); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/IntrospectionController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | using Authlete.Web; 25 | 26 | 27 | namespace AuthorizationServer.Controllers 28 | { 29 | /// 30 | /// An implementation of introspection endpoint 31 | /// (RFC 7662). 32 | /// 33 | [Route("api/[controller]")] 34 | public class IntrospectionController : BaseController 35 | { 36 | public IntrospectionController(IAuthleteApi api) : base(api) 37 | { 38 | } 39 | 40 | 41 | /// 42 | /// Introspection endpoint. 43 | /// 44 | [HttpPost] 45 | [Consumes("application/x-www-form-urlencoded")] 46 | public async Task Post() 47 | { 48 | // "2.1. Introspection Request" in RFC 7662 says as 49 | // follows: 50 | // 51 | // To prevent token scanning attacks, the endpoint 52 | // MUST also require some form of authorization to 53 | // access this endpoint, such as client 54 | // authentication as described in OAuth 2.0 [RFC6749] 55 | // or a separate OAuth 2.0 access token such as the 56 | // bearer token described in OAuth 2.0 Bearer Token 57 | // Usage [RFC6750]. The methods of managing and 58 | // validating these authentication credentials are 59 | // out of scope of this specification. 60 | // 61 | // So, this API must be protected in some way or other. 62 | // Let's perform authentication of the API caller. 63 | bool authenticated = AuthenticateApiCaller(); 64 | 65 | // If the API caller does not have necessary 66 | // privileges to call this API. 67 | if (authenticated == false) 68 | { 69 | // Return "401 Unauthorized". 70 | return GenerateUnauthorizedError(); 71 | } 72 | 73 | // Request parameters. 74 | string parameters = await ReadRequestBodyAsString(); 75 | 76 | // Call Authlete's /api/auth/introspection/standard API. 77 | return await new IntrospectionRequestHandler(API) 78 | .Handle(parameters); 79 | } 80 | 81 | 82 | bool AuthenticateApiCaller() 83 | { 84 | // NOTE: 85 | // THIS IMPLEMENTATION IS DEMONSTRATION PURPOSES ONLY. 86 | 87 | // Get the value of the Authorization header. 88 | string auth = GetRequestHeaderValue("Authorization"); 89 | 90 | // Try to parse it as "Basic Authentication". 91 | BasicCredentials credentials = 92 | BasicCredentials.Parse(auth); 93 | 94 | // If the Authorization header does not contain 95 | // "Basic Authentication" or the user ID is not valid. 96 | if (credentials == null || credentials.UserId == null) 97 | { 98 | // Authentication of the API caller failed. 99 | return false; 100 | } 101 | 102 | // If the user ID is "nobody". 103 | if ("nobody".Equals(credentials.UserId)) 104 | { 105 | // Reject the introspection request by "nobody". 106 | return false; 107 | } 108 | 109 | // Accept anybody except "nobody" regardless of 110 | // whatever the value of credentials.Password is. 111 | return true; 112 | } 113 | 114 | 115 | HttpResponseMessage GenerateUnauthorizedError() 116 | { 117 | // NOTE: 118 | // THIS IMPLEMENTATION IS DEMONSTRATION PURPOSES ONLY. 119 | 120 | // Prepare a value of the WWW-Authenticate header. 121 | // Note that the implementation of AuthenticateApiCaller() 122 | // requires Basic Authentication. 123 | string challenge = "Basic realm=\"/api/introspection\""; 124 | 125 | // Return "401 Unauthorized". 126 | return ResponseUtility.Unauthorized(challenge); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/JwksController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | 25 | 26 | namespace AuthorizationServer.Controllers 27 | { 28 | /// 29 | /// An implementation of an endpoint to expose a JSON Web Key 30 | /// Set document 31 | /// (RFC 7517). 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// An OpenID Provider (OP) is required to expose its JSON Web 37 | /// Key Set document (JWK Set) so that client applications can 38 | /// (1) verify signatures by the OP and (2) encrypt their 39 | /// requests to the OP. The URI of a JWK Set document endpoint 40 | /// can be found as the value of the "jwks_uri" metadata 41 | /// defined in 42 | /// OpenID 43 | /// Provider Metadata if the OP supports 44 | /// OpenID 45 | /// Connect Discovery 1.0. 46 | /// 47 | /// 48 | [Route("api/[controller]")] 49 | public class JwksController : BaseController 50 | { 51 | public JwksController(IAuthleteApi api) : base(api) 52 | { 53 | } 54 | 55 | 56 | /// 57 | /// JWK Set document endpoint. 58 | /// 59 | [HttpGet] 60 | public async Task Get() 61 | { 62 | // Call Authlete's /api/service/jwks/get API. 63 | return await new JwksRequestHandler(API).Handle(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/RevocationController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | 25 | 26 | namespace AuthorizationServer.Controllers 27 | { 28 | /// 29 | /// An implementation of revocation endpoint 30 | /// (RFC 7009). 31 | /// 32 | [Route("api/[controller]")] 33 | public class RevocationController : BaseController 34 | { 35 | public RevocationController(IAuthleteApi api) : base(api) 36 | { 37 | } 38 | 39 | 40 | /// 41 | /// Revocation endpoint. 42 | /// 43 | [HttpPost] 44 | [Consumes("application/x-www-form-urlencoded")] 45 | public async Task Post() 46 | { 47 | // Request parameters. 48 | string parameters = await ReadRequestBodyAsString(); 49 | 50 | // The value of the Authorization header. 51 | string auth = GetRequestHeaderValue("Authorization"); 52 | 53 | // Call Authlete's /api/auth/revocation API. 54 | return await new RevocationRequestHandler(API) 55 | .Handle(parameters, auth); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AuthorizationServer/Controllers/TokenController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.Net.Http; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Authlete.Api; 23 | using Authlete.Handler; 24 | using AuthorizationServer.Spi; 25 | 26 | 27 | namespace AuthorizationServer.Controllers 28 | { 29 | /// 30 | /// An implementation of OAuth 2.0 31 | /// token 32 | /// endpoint with OpenID 33 | /// Connect support. 34 | /// 35 | [Route("api/[controller]")] 36 | public class TokenController : BaseController 37 | { 38 | public TokenController(IAuthleteApi api) : base(api) 39 | { 40 | } 41 | 42 | 43 | /// 44 | /// Token endpoint. 45 | /// 46 | [HttpPost] 47 | [Consumes("application/x-www-form-urlencoded")] 48 | public async Task Post() 49 | { 50 | // Request parameters. 51 | string parameters = await ReadRequestBodyAsString(); 52 | 53 | // The value of the Authorization header. 54 | string auth = GetRequestHeaderValue("Authorization"); 55 | 56 | // Handle the token request. 57 | return await new TokenRequestHandler( 58 | API, new TokenRequestHandlerSpiImpl()) 59 | .Handle(parameters, auth); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /AuthorizationServer/Db/UserDao.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Authlete.Dto; 20 | 21 | 22 | namespace AuthorizationServer.Db 23 | { 24 | /// 25 | /// Dummy database operations for a user table. 26 | /// 27 | public class UserDao 28 | { 29 | // Dummy user database table. 30 | static readonly UserEntity[] USER_DB = 31 | { 32 | new UserEntity 33 | { 34 | Subject = "1001", 35 | LoginId = "john", 36 | Password = "john", 37 | Name = "John Smith", 38 | Email = "john@example.com", 39 | Address = new Address { Country = "USA"}, 40 | PhoneNumber = "+1 (425) 555-1212" 41 | }, 42 | new UserEntity 43 | { 44 | Subject = "1002", 45 | LoginId = "jane", 46 | Password = "jane", 47 | Name = "Jane Smith", 48 | Email = "jane@example.com", 49 | Address = new Address { Country = "Chile"}, 50 | PhoneNumber = "+56 (2) 687 2400" 51 | } 52 | }; 53 | 54 | 55 | /// 56 | /// Get a user entity by a pair of login ID ans password. 57 | /// 58 | public static UserEntity GetByCredentials( 59 | string loginId, string password) 60 | { 61 | // For each record in the dummy user database table. 62 | foreach (UserEntity entity in USER_DB) 63 | { 64 | // If the login credentials are valid. 65 | if (entity.LoginId.Equals(loginId) && 66 | entity.Password.Equals(password)) 67 | { 68 | // Found the user who has the login credentials. 69 | return entity; 70 | } 71 | } 72 | 73 | // Not found any user who has the login credentials. 74 | return null; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /AuthorizationServer/Db/UserEntity.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Authlete.Dto; 20 | using Authlete.Types; 21 | 22 | 23 | namespace AuthorizationServer.Db 24 | { 25 | /// 26 | /// Dummy user entity that represents a user record. 27 | /// 28 | public class UserEntity 29 | { 30 | /// 31 | /// The subject (= unique identifier) of the user. 32 | /// 33 | public string Subject { get; set; } 34 | 35 | 36 | /// 37 | /// Login ID. 38 | /// 39 | public string LoginId { get; set; } 40 | 41 | 42 | /// 43 | /// Login password. 44 | /// 45 | public string Password { get; set; } 46 | 47 | 48 | /// 49 | /// The name of the user. 50 | /// 51 | public string Name { get; set; } 52 | 53 | 54 | /// 55 | /// Email address. 56 | /// 57 | public string Email { get; set; } 58 | 59 | 60 | /// 61 | /// Postal address. 62 | /// 63 | public Address Address { get; set; } 64 | 65 | 66 | /// 67 | /// Phone number. 68 | /// 69 | public string PhoneNumber { get; set; } 70 | 71 | 72 | /// 73 | /// Get the claim value of a claim. 74 | /// 75 | public object GetClaimValue(string claimName) 76 | { 77 | // See "OpenID Connect Core 1.0, 5. Claims". 78 | switch (claimName) 79 | { 80 | case StandardClaims.NAME: 81 | // "name" claim. This claim can be requested by 82 | // including "profile" in the "scope" parameter 83 | // of an authorization request. 84 | return Name; 85 | 86 | case StandardClaims.EMAIL: 87 | // "email" claim. This claim can be requested 88 | // by including "email" in the "scope" 89 | // parameter of an authorization request. 90 | return Email; 91 | 92 | case StandardClaims.ADDRESS: 93 | // "address" claim. This claim can be requested 94 | // by including "address" in the "scope" 95 | // parameter of an authorization request. 96 | return Address; 97 | 98 | case StandardClaims.PHONE_NUMBER: 99 | // "phone_number" claim. This claim can be 100 | // requested by including "phone" in the "scope" 101 | // parameter of an authorization request. 102 | return PhoneNumber; 103 | 104 | default: 105 | // Unsupported claim. 106 | return null; 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /AuthorizationServer/Models/AuthorizationPageModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System; 20 | using Authlete.Dto; 21 | using AuthorizationServer.Db; 22 | 23 | 24 | namespace AuthorizationServer.Models 25 | { 26 | /// 27 | /// Model for the authorization page. 28 | /// See Controllers/AuthorizationController.cs and 29 | /// Views/Authorization/Page.cshtml. 30 | /// 31 | public class AuthorizationPageModel 32 | { 33 | public AuthorizationPageModel( 34 | AuthorizationResponse response, UserEntity user) 35 | { 36 | Client client = response.Client; 37 | 38 | ServiceName = response.Service.ServiceName; 39 | ClientName = client.ClientName; 40 | Description = client.Description; 41 | LogoUri = UriToString(client.LogoUri); 42 | ClientUri = UriToString(client.ClientUri); 43 | PolicyUri = UriToString(client.PolicyUri); 44 | TosUri = UriToString(client.TosUri); 45 | Scopes = response.Scopes; 46 | LoginId = ComputeLoginId(response); 47 | LoginIdReadOnly = ComputeLoginIdReadOnly(response); 48 | User = user; 49 | } 50 | 51 | 52 | /// 53 | /// The name of the service. 54 | /// 55 | public string ServiceName { get; } 56 | 57 | 58 | /// 59 | /// The name of the client application. 60 | /// 61 | public string ClientName { get; } 62 | 63 | 64 | /// 65 | /// The description of the client application. 66 | /// 67 | public string Description { get; } 68 | 69 | 70 | /// 71 | /// The URL of the logo image of the client application. 72 | /// 73 | public string LogoUri { get; } 74 | 75 | 76 | /// 77 | /// The URL of the homepage of the client application. 78 | /// 79 | public string ClientUri { get; } 80 | 81 | 82 | /// 83 | /// The URL of the policy page of the client application. 84 | /// 85 | public string PolicyUri { get; } 86 | 87 | 88 | /// 89 | /// The URL of "Terms of Service" page of the client 90 | /// application. 91 | /// 92 | public string TosUri { get; } 93 | 94 | 95 | /// 96 | /// Scopes requested by the authorization request. 97 | /// 98 | public Scope[] Scopes { get; } 99 | 100 | 101 | /// 102 | /// The login ID that should be used as the initial value 103 | /// for the login ID field in the authorization page. 104 | /// 105 | public string LoginId { get; } 106 | 107 | 108 | /// 109 | /// This property holds a string "readonly" whne the 110 | /// initial value of the login ID should not be changed. 111 | /// 112 | public string LoginIdReadOnly { get; } 113 | 114 | 115 | /// 116 | /// The current user. This is null if no user has 117 | /// logged in. 118 | /// 119 | public UserEntity User { get; } 120 | 121 | 122 | /// 123 | /// Get the string representation of the given URI. 124 | /// 125 | static string UriToString(Uri uri) 126 | { 127 | return (uri == null) ? null : uri.ToString(); 128 | } 129 | 130 | 131 | /// 132 | /// Compute the initial value for the login ID field in the 133 | /// authorization page. 134 | /// 135 | static string ComputeLoginId(AuthorizationResponse response) 136 | { 137 | if (response.Subject != null) 138 | { 139 | return response.Subject; 140 | } 141 | 142 | return response.LoginHint; 143 | } 144 | 145 | 146 | /// 147 | /// Return "readonly" if the authorization request 148 | /// requires that a specific subject be used. 149 | /// 150 | static string ComputeLoginIdReadOnly(AuthorizationResponse response) 151 | { 152 | if (response.Subject != null) 153 | { 154 | return "readonly"; 155 | } 156 | else 157 | { 158 | return null; 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /AuthorizationServer/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | 5 | namespace AuthorizationServer 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | BuildWebHost(args).Run(); 12 | } 13 | 14 | 15 | public static IWebHost BuildWebHost(string[] args) => 16 | WebHost.CreateDefaultBuilder(args) 17 | .UseStartup() 18 | .Build(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AuthorizationServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:55556/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "api/values", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "AuthorizationServer": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "api/values", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "http://localhost:5000/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /AuthorizationServer/Spi/AuthorizationRequestDecisionHandlerSpiImpl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Microsoft.AspNetCore.Mvc; 20 | using Authlete.Handler.Spi; 21 | 22 | 23 | namespace AuthorizationServer.Spi 24 | { 25 | public class AuthorizationRequestDecisionHandlerSpiImpl 26 | : AuthorizationRequestHandlerSpiImpl, 27 | IAuthorizationRequestDecisionHandlerSpi 28 | { 29 | readonly bool _clientAuthorized; 30 | 31 | 32 | public AuthorizationRequestDecisionHandlerSpiImpl( 33 | Controller controller, bool clientAuthorized) 34 | : base(controller) 35 | { 36 | _clientAuthorized = clientAuthorized; 37 | } 38 | 39 | 40 | public bool IsClientAuthorized() 41 | { 42 | return _clientAuthorized; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AuthorizationServer/Spi/AuthorizationRequestHandlerSpiImpl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Microsoft.AspNetCore.Mvc; 20 | using Authlete.Handler.Spi; 21 | using AuthorizationServer.Db; 22 | using AuthorizationServer.Util; 23 | 24 | 25 | namespace AuthorizationServer.Spi 26 | { 27 | public class AuthorizationRequestHandlerSpiImpl 28 | : AuthorizationRequestHandlerSpiAdapter 29 | { 30 | readonly UserTData _userTData; 31 | 32 | 33 | public AuthorizationRequestHandlerSpiImpl(Controller controller) 34 | { 35 | // Wrap TempData. 36 | _userTData = new UserTData(controller.TempData); 37 | } 38 | 39 | 40 | public override object GetUserClaimValue( 41 | string subject, string claimName, string languageTag) 42 | { 43 | // Get the UserEntity from TempData. 44 | UserEntity entity = _userTData.GetUserEntity(); 45 | 46 | // If TempData does not hold a UserEntity. 47 | if (entity == null) 48 | { 49 | // Claim value is not available. 50 | return null; 51 | } 52 | 53 | // Get the value of the claim. 54 | return entity.GetClaimValue(claimName); 55 | } 56 | 57 | 58 | public override long GetUserAuthenticatedAt() 59 | { 60 | // Get the authentication time from TempData. 61 | return _userTData.GetUserAuthenticatedAt(); 62 | } 63 | 64 | 65 | public override string GetUserSubject() 66 | { 67 | // Get the UserEntity from TempData. 68 | UserEntity entity = _userTData.GetUserEntity(); 69 | 70 | // If TempData does not hold a UserEntity. 71 | if (entity == null) 72 | { 73 | // User information is not available. 74 | return null; 75 | } 76 | 77 | // Return the subject (= unique identifier) of the user. 78 | return entity.Subject; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /AuthorizationServer/Spi/NoInteractionHandlerSpiImpl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Microsoft.AspNetCore.Mvc; 20 | using Authlete.Handler.Spi; 21 | 22 | 23 | namespace AuthorizationServer.Spi 24 | { 25 | public class NoInteractionHandlerSpiImpl 26 | : AuthorizationRequestHandlerSpiImpl, 27 | INoInteractionHandlerSpi 28 | { 29 | public NoInteractionHandlerSpiImpl(Controller controller) 30 | : base(controller) 31 | { 32 | } 33 | 34 | 35 | public bool IsUserAuthenticated() 36 | { 37 | return (GetUserSubject() != null); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /AuthorizationServer/Spi/TokenRequestHandlerSpiImpl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Authlete.Handler.Spi; 20 | using AuthorizationServer.Db; 21 | 22 | 23 | namespace AuthorizationServer.Spi 24 | { 25 | public class TokenRequestHandlerSpiImpl 26 | : TokenRequestHandlerSpiAdapter 27 | { 28 | public override string AuthenticateUser( 29 | string username, string password) 30 | { 31 | // NOTE: 32 | // This method needs to be implemented only when you 33 | // want to support "Resource Owner Password Credentials" 34 | // flow (RFC 6749, 4.3). 35 | 36 | // Search the user database for the user. 37 | UserEntity entity = 38 | UserDao.GetByCredentials(username, password); 39 | 40 | // If not found. 41 | if (entity == null) 42 | { 43 | // There is no user who has the credentials. 44 | return null; 45 | } 46 | 47 | // Return the subject (= unique identifier) of the user. 48 | return entity.Subject; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AuthorizationServer/Startup.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Microsoft.AspNetCore.Builder; 20 | using Microsoft.AspNetCore.Hosting; 21 | using Microsoft.Extensions.Configuration; 22 | using Microsoft.Extensions.DependencyInjection; 23 | using Authlete.Api; 24 | using Authlete.Conf; 25 | 26 | 27 | namespace AuthorizationServer 28 | { 29 | public class Startup 30 | { 31 | public Startup(IConfiguration configuration) 32 | { 33 | Configuration = configuration; 34 | } 35 | 36 | 37 | public IConfiguration Configuration { get; } 38 | 39 | 40 | public void ConfigureServices(IServiceCollection services) 41 | { 42 | // AddWebApiConventions() is added by WebApiCompatShim. 43 | // Calling the method enables Web API implementations 44 | // to return an HttpResponseMessage instance directly. 45 | services.AddMvc().AddWebApiConventions(); 46 | 47 | // Register an instance of IAuthleteApi so controllers 48 | // can refer to it in order to call Authlete Web APIs. 49 | // IAuthleteApi instance will be passed to constructors 50 | // of controllers by 'Dependency Injection'. Read the 51 | // following article for details. 52 | // 53 | // Introduction to Dependency Injection in ASP.NET Core 54 | // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection 55 | // 56 | services.AddSingleton(CreateAuthleteApi()); 57 | } 58 | 59 | 60 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 61 | { 62 | if (env.IsDevelopment()) 63 | { 64 | app.UseDeveloperExceptionPage(); 65 | } 66 | 67 | app.UseDefaultFiles(); 68 | app.UseStaticFiles(); 69 | app.UseMvc(); 70 | } 71 | 72 | 73 | static IAuthleteApi CreateAuthleteApi() 74 | { 75 | // Create an instance of IAuthleteConfiguration. 76 | var conf = CreateAuthleteConfiguration(); 77 | 78 | // Create an instance of IAuthleteApi. 79 | return new AuthleteApi(conf); 80 | } 81 | 82 | 83 | static IAuthleteConfiguration CreateAuthleteConfiguration() 84 | { 85 | // Load a configuration file and build an instance of 86 | // IAuthleteConfiguration interface. By default, 87 | // "authlete.properties" will be loaded. The name of a 88 | // configuration file can be specified by the 89 | // environment variable, AUTHLETE_CONFIGURATION_FILE. 90 | // 91 | // AuthetePropertiesConfiguration class has three 92 | // constructors one of which explicitly takes the name 93 | // of a configuration file. 94 | // 95 | // In Authlete.Conf namespace, there exist some other 96 | // implementations of IAuthleteConfiguration interface. 97 | 98 | return new AuthletePropertiesConfiguration(); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /AuthorizationServer/Util/Renderer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System.IO; 20 | using System.Threading.Tasks; 21 | using Microsoft.AspNetCore.Mvc; 22 | using Microsoft.AspNetCore.Mvc.ViewEngines; 23 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 24 | using Microsoft.AspNetCore.Mvc.Rendering; 25 | 26 | 27 | namespace AuthorizationServer.Util 28 | { 29 | /// 30 | /// Utility to render a view manually. 31 | /// 32 | public class Renderer 33 | { 34 | readonly Controller _controller; 35 | readonly IViewEngine _viewEngine; 36 | 37 | 38 | public Renderer(Controller controller, IViewEngine engine) 39 | { 40 | _controller = controller; 41 | _viewEngine = engine; 42 | } 43 | 44 | 45 | public async Task Render(object model) 46 | { 47 | string viewName = 48 | _controller.ControllerContext.ActionDescriptor.ActionName; 49 | 50 | return await Render(viewName, model); 51 | } 52 | 53 | 54 | public async Task Render(string viewName, object model) 55 | { 56 | _controller.ViewData.Model = model; 57 | 58 | var result = CreateViewEngineResult(viewName); 59 | 60 | using (var writer = new StringWriter()) 61 | { 62 | // Prepare a context for rendering. 63 | var context = CreateViewContext(result, writer); 64 | 65 | // Render the view. 66 | await result.View.RenderAsync(context); 67 | 68 | // Convert the rendering result to a string. 69 | return writer.GetStringBuilder().ToString(); 70 | } 71 | } 72 | 73 | 74 | ViewEngineResult CreateViewEngineResult(string viewName) 75 | { 76 | return _viewEngine.FindView( 77 | _controller.ControllerContext, viewName, false); 78 | } 79 | 80 | 81 | ViewContext CreateViewContext( 82 | ViewEngineResult result, TextWriter writer) 83 | { 84 | return new ViewContext( 85 | _controller.ControllerContext, 86 | result.View, 87 | _controller.ViewData, 88 | _controller.TempData, 89 | writer, 90 | new HtmlHelperOptions() 91 | ); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /AuthorizationServer/Util/TData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using System; 20 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 21 | using Authlete.Util; 22 | 23 | 24 | namespace AuthorizationServer.Util 25 | { 26 | /// 27 | /// Wrapper over ITempDataDictionary. 28 | /// 29 | public class TData 30 | { 31 | readonly ITempDataDictionary _tempdata; 32 | 33 | 34 | public TData(ITempDataDictionary tempdata) 35 | { 36 | _tempdata = tempdata; 37 | } 38 | 39 | 40 | public object Get(string key) 41 | { 42 | return _tempdata.Peek(key); 43 | } 44 | 45 | 46 | public object Get(object key) 47 | { 48 | return Get(key.ToString()); 49 | } 50 | 51 | 52 | public T GetObject(string key) 53 | { 54 | return TextUtility.FromJson((string)Get(key)); 55 | } 56 | 57 | 58 | public T GetObject(object key) 59 | { 60 | return GetObject(key.ToString()); 61 | } 62 | 63 | 64 | public long GetLong(string key) 65 | { 66 | object value = Get(key); 67 | 68 | if (value == null) 69 | { 70 | return default(long); 71 | } 72 | 73 | return Convert.ToInt64(value); 74 | } 75 | 76 | 77 | public long GetLong(object key) 78 | { 79 | return GetLong(key.ToString()); 80 | } 81 | 82 | 83 | public void Set(string key, object data) 84 | { 85 | _tempdata[key] = data; 86 | } 87 | 88 | 89 | public void Set(object key, object data) 90 | { 91 | Set(key.ToString(), data); 92 | } 93 | 94 | 95 | public void SetObject(string key, object data) 96 | { 97 | Set(key, TextUtility.ToJson(data)); 98 | } 99 | 100 | 101 | public void SetObject(object key, object data) 102 | { 103 | SetObject(key.ToString(), data); 104 | } 105 | 106 | 107 | public void SetLong(string key, long data) 108 | { 109 | Set(key, data); 110 | } 111 | 112 | 113 | public void SetLong(object key, long data) 114 | { 115 | SetLong(key.ToString(), data); 116 | } 117 | 118 | 119 | public void Remove(string key) 120 | { 121 | _tempdata.Remove(key); 122 | } 123 | 124 | 125 | public void Remove(object key) 126 | { 127 | Remove(key.ToString()); 128 | } 129 | 130 | 131 | public void Clear() 132 | { 133 | _tempdata.Clear(); 134 | } 135 | 136 | 137 | public bool ContainsKey(string key) 138 | { 139 | return _tempdata.ContainsKey(key); 140 | } 141 | 142 | 143 | public bool ContainsKey(object key) 144 | { 145 | return ContainsKey(key.ToString()); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /AuthorizationServer/Util/UserTData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Authlete, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 13 | // either express or implied. See the License for the specific 14 | // language governing permissions and limitations under the 15 | // License. 16 | // 17 | 18 | 19 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 20 | using AuthorizationServer.Db; 21 | 22 | 23 | namespace AuthorizationServer.Util 24 | { 25 | public class UserTData : TData 26 | { 27 | enum Key 28 | { 29 | USER_AUTHENTICATED_AT, 30 | USER_ENTITY, 31 | } 32 | 33 | 34 | public UserTData(ITempDataDictionary tempdata) 35 | : base(tempdata) 36 | { 37 | } 38 | 39 | 40 | public UserEntity GetUserEntity() 41 | { 42 | return GetObject(Key.USER_ENTITY); 43 | } 44 | 45 | 46 | public void SetUserEntity(UserEntity entity) 47 | { 48 | SetObject(Key.USER_ENTITY, entity); 49 | } 50 | 51 | 52 | public void RemoveUserEntity() 53 | { 54 | Remove(Key.USER_ENTITY); 55 | } 56 | 57 | 58 | public bool HasUserEntity() 59 | { 60 | return ContainsKey(Key.USER_ENTITY); 61 | } 62 | 63 | 64 | public long GetUserAuthenticatedAt() 65 | { 66 | return GetLong(Key.USER_AUTHENTICATED_AT); 67 | } 68 | 69 | 70 | public void SetUserAuthenticatedAt(long time) 71 | { 72 | SetLong(Key.USER_AUTHENTICATED_AT, time); 73 | } 74 | 75 | 76 | public void RemoveUserAuthenticatedAt() 77 | { 78 | Remove(Key.USER_AUTHENTICATED_AT); 79 | } 80 | 81 | 82 | public void RemoveUserTData() 83 | { 84 | RemoveUserEntity(); 85 | RemoveUserAuthenticatedAt(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /AuthorizationServer/Views/Authorization/Page.cshtml: -------------------------------------------------------------------------------- 1 | @model AuthorizationServer.Models.AuthorizationPageModel 2 | 3 | 4 | 5 | 6 | @Model.ServiceName | Authorization Page 7 | 8 | 9 | 10 |
@Model.ServiceName
11 | 12 |
13 |

@Model.ClientName

14 |
15 | 16 | 17 |
18 |

@Model.Description

19 | 33 |
34 | 35 |
36 |
37 | 38 | @if (Model.Scopes != null) 39 | { 40 |

Permissions

41 |
42 |

The application is requesting the following permissions.

43 |
44 | @foreach (var scope in Model.Scopes) 45 | { 46 |
@scope.Name
47 |
@scope.Description
48 | } 49 |
50 |
51 | } 52 | 53 |

Authorization

54 |
55 | @if (Model.User != null) 56 | { 57 |

Hello @Model.User.Name,

58 | } 59 |

Do you grant authorization to the application?

60 | 61 |
62 | @if (Model.User == null) 63 | { 64 |
65 |
Input Login ID and password.
66 | 68 | 70 |
71 | } 72 |
73 | 74 | 75 |
76 |
77 |
78 |
79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /AuthorizationServer/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /AuthorizationServer/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 | } 15 | } 16 | -------------------------------------------------------------------------------- /AuthorizationServer/authlete.properties: -------------------------------------------------------------------------------- 1 | #=================================================================== 2 | # Authlete Configuration File 3 | # 4 | # There are several ways to construct an IAuthleteConfiguration 5 | # instance which represents "authlete configuration". 6 | # AuthletePropertiesConfiguration is one of implementations of 7 | # the IAuthleteConfiguration interface. This file can be used 8 | # as input for AuthletePropertiesConfiguration. See the API 9 | # document of authlete-csharp library for details. 10 | # 11 | # authlete-csharp library 12 | # Source: https://github.com/authlete/authlete-csharp 13 | # API Doc: https://authlete.github.io/authlete-csharp/ 14 | # NuGet: https://www.nuget.org/packages/Authlete.Authlete 15 | # 16 | #=================================================================== 17 | 18 | 19 | # base_url 20 | # 21 | # The base URL of an Authlete server. If you are using the 22 | # shared server, set "https://api.authlete.com" to this 23 | # parameter. On the other hand, if you are using a dedicated 24 | # server, please contact "Authlete, Inc." 25 | # about the URL of your dedicated Authlete server. 26 | # 27 | base_url = https://api.authlete.com 28 | 29 | 30 | # service.api_key 31 | # service.api_secret 32 | # 33 | # API credentials of one of your services. You can find API 34 | # credentials of your services in Service Owner Console. The 35 | # location of the web console is "https://so.authlete.com/" 36 | # if you are using the shared server. On the other hand, if 37 | # you are using a dedicated server, please contact 38 | # "Authlete, Inc." about the location 39 | # of the web console of your dedicated Authlete server. 40 | # 41 | service.api_key = 5593494639 42 | service.api_secret = AAw0rner_-y1A6J9s20wjRCpkBvez3GxEBoL9jOJVR0 43 | service.access_token = 44 | 45 | 46 | # service_owner.api_key 47 | # service_owner.api_secret 48 | # 49 | # API credentials of your account (service owner). Some 50 | # Authlete APIs require API credentials of a serivce owner 51 | # instead of a service. 52 | # 53 | service_owner.api_key = 54 | service_owner.api_secret = 55 | service_owner.access_token = 56 | 57 | -------------------------------------------------------------------------------- /AuthorizationServer/wwwroot/css/authorization.css: -------------------------------------------------------------------------------- 1 | .font-default 2 | { 3 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Segoe UI', 'Arial', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | color: #666; 6 | } 7 | 8 | body { 9 | margin: 0; 10 | text-shadow: none; 11 | } 12 | 13 | p { 14 | margin-top: 0; 15 | } 16 | 17 | h3, h4 { 18 | color: steelblue; 19 | } 20 | 21 | .indent { 22 | margin-left: 15px; 23 | } 24 | 25 | #page_title { 26 | background: #F5F5F5; 27 | color: steelblue; 28 | padding: 0.5em; 29 | margin: 0; 30 | } 31 | 32 | #content { 33 | padding: 0 20px 20px; 34 | } 35 | 36 | #logo { 37 | width: 150px; 38 | height: 150px; 39 | background: lightgray; 40 | margin: 0 20px 10px 5px; 41 | float: left; 42 | } 43 | 44 | #client-summary { 45 | float: left; 46 | } 47 | 48 | #client-link-list { 49 | margin: 0; 50 | padding: 0; 51 | } 52 | 53 | #client-link-list li { 54 | list-style-type: none; 55 | } 56 | 57 | #client-link-list a { 58 | position: relative; 59 | padding-left: 25px; 60 | text-decoration: none; 61 | color: cadetblue; 62 | } 63 | 64 | #client-link-list a:hover { 65 | text-decoration: underline; 66 | } 67 | 68 | #client-link-list a:before { 69 | display: block; 70 | content: ""; 71 | position: absolute; 72 | top: 50%; 73 | left: 0; 74 | width: 0; 75 | margin: -5px 0 0 0; 76 | border-top: 12px solid cadetblue; 77 | border-left: 12px solid transparent; 78 | -webkit-transform: rotate(45deg); 79 | transform: rotate(45deg); 80 | } 81 | 82 | #scope-list { 83 | margin-left: 20px; 84 | } 85 | 86 | #scope-list dt { 87 | font-weight: bold; 88 | } 89 | 90 | #scope-list dd { 91 | margin-bottom: 10px; 92 | } 93 | 94 | input { 95 | color: black; 96 | } 97 | 98 | #login-fields { 99 | margin-bottom: 20px; 100 | } 101 | 102 | #login-prompt { 103 | font-size: 85%; 104 | margin-bottom: 5px; 105 | } 106 | 107 | #loginId { 108 | display: block; 109 | border: 1px solid #666; 110 | border-bottom: none; 111 | padding: 0.3em 0.5em; 112 | width: 300px; 113 | } 114 | 115 | #password { 116 | display: block; 117 | border: 1px solid #666; 118 | padding: 0.3em 0.5em; 119 | width: 300px; 120 | } 121 | 122 | #authorization-form-buttons { 123 | margin: 20px auto; 124 | } 125 | 126 | #authorize-button, #deny-button { 127 | display: inline-block; 128 | width: 150px; 129 | padding: 12px 0; 130 | margin: 13px; 131 | min-height: 26px; 132 | text-align: center; 133 | text-decoration: none; 134 | outline: 0; 135 | -webkit-transition: none; 136 | transition: none; 137 | } 138 | 139 | #authorize-button { 140 | background-color: #4285f4; 141 | color: white; 142 | } 143 | 144 | #authorize-button:hover { 145 | background-color: #1255f4; 146 | } 147 | 148 | #authorize-button:active { 149 | background-color: blue; 150 | } 151 | 152 | #deny-button { 153 | background-color: #f08080; 154 | color: white; 155 | } 156 | 157 | #deny-button:hover { 158 | background-color: #f05050; 159 | } 160 | 161 | #deny-button:active { 162 | background-color: red; 163 | } 164 | -------------------------------------------------------------------------------- /AuthorizationServer/wwwroot/css/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | text-shadow: none; 4 | } 5 | 6 | #page_title { 7 | background: #333; 8 | color: white; 9 | padding: 0.5em; 10 | margin: 0; 11 | font-size: 200%; 12 | } 13 | 14 | #content { 15 | padding: 20px; 16 | } 17 | 18 | table { 19 | border-collapse: collapse; 20 | } 21 | 22 | td { 23 | padding: 10px; 24 | } 25 | 26 | tr.label, td.label { 27 | background-color: #E0E0E0; 28 | } 29 | 30 | a { 31 | text-decoration: none; 32 | color: blue; 33 | } 34 | 35 | a:visited { 36 | color: blue; 37 | } 38 | 39 | a:hover { 40 | text-decoration: underline; 41 | } 42 | 43 | .font-default 44 | { 45 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Segoe UI', 'Arial', sans-serif; 46 | -webkit-font-smoothing: antialiased; 47 | } 48 | -------------------------------------------------------------------------------- /AuthorizationServer/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Authorization Server 7 | 8 | 9 | 10 |
Authorization Server
11 | 12 |
13 |

14 | Authorization server supporting OAuth 2.0 & OpenID Connect, powered by 15 | Authlete. 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 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
EndpointPath
Authorization Endpoint/api/authorization
Token Endpoint/api/token
JWK Set document Endpoint/api/jwks
Configuration Endpoint/.well-known/openid-configuration
Revocation Endpoint/api/revocation
Introspection Endpoint/api/introspection
52 | 53 | 54 | 55 | 56 | 57 | 60 | 61 | 62 | 63 | 67 | 68 | 69 | 70 | 71 | 75 | 76 | 77 | 78 | 82 | 83 | 84 |
Management Console 58 | https://so.authlete.com 59 |
Source Code 64 | https://github.com/authlete/csharp-oauth-server 66 |
LibrarySource 72 | https://github.com/authlete/authlete-csharp 74 |
NuGet 79 | https://www.nuget.org/packages/Authlete.Authlete 81 |
85 | 86 |
    87 |
  1. 88 | Authlete 89 | is an OAuth 2.0 & OpenID Connect implementation on cloud. 90 |
  2. 91 | This authorization server is written using Authlete's open source library 92 | (Authlete.Authlete). 94 |
  3. 95 | This authorization server is DB-less because authorization data are stored on cloud. 96 |
  4. 97 | You can manage settings of authorization servers by 98 | Service Owner Console 99 | (document). 100 |
  5. 101 | You can manage settings of client applications by Developer Console 102 | (document). 103 |
104 |
105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /CUSTOMIZATION.ja.md: -------------------------------------------------------------------------------- 1 | カスタマイズ 2 | ============ 3 | 4 | このドキュメントでは、この認可サーバーの実装をカスタマイズする方法を説明します。 5 | 6 | 7 | 概要 8 | ---- 9 | 10 | この認可サーバーの実装では、[Authlete][1] をバックエンドとして使用しています。 11 | これは、(1) [OAuth 2.0][2] と [OpenID Connect][3] の実装の中心となる部分が 12 | csharp-oauth-server のソースツリー内ではなくクラウド上の Authlete 13 | サーバー内にあること、そして (2) 14 | アクセストークンなどの認可データ、認可サーバー自体の設定やクライアントアプリケーションの設定が、 15 | ローカルデータベース内ではなくクラウド上のデータベースに保存されるということ、 16 | を意味します。 そのため、非常に単純化して言うと、次の図が示すように、 17 | この実装はクライアントアプリケーションと Authlete サーバーの間の仲介役でしかありません。 18 | 19 | ``` 20 | +--------+ +---------------------+ +----------+ 21 | | | | | | | 22 | | Client | <------> | csharp-oauth-server | <------> | Authlete | 23 | | | | | | | 24 | +--------+ +---------------------+ +----------+ 25 | ``` 26 | 27 | とはいえ、Authlete は**認可**に特化しており、エンドユーザーの**認証**に関することは何もしないので、 28 | 認証に関わる機能は csharp-oauth-server のソースツリー内に実装されています。 29 | 30 | ですので、少なくとも、エンドユーザーの認証に関する部分についてはカスタマイズが必要です。 31 | 一方、認可画面の UI デザインなどの他の部分のカスタマイズは任意です。 32 | 33 | 34 | 全体の構成 35 | ---------- 36 | 37 | Authlete が提供する [Web API][4] を使い、認可サーバーを実装することができます。 38 | [authlete-csharp][5] ライブラリは、Authlete Web API と直接やりとりするための 39 | `IAuthleteApi` インターフェースとその実装を含んでいます。 また、`IAuthleteApi` 40 | をラッピングするユーティリティークラス群も含んでおり、それらのクラス群を使えば、 41 | Authlete API を直接使用するよりもかなり簡単に認可サーバーを書くことができます。 42 | 43 | [authlete-csharp][5] ライブラリは、NuGet パッケージ [Authlete.Authlete][6] 44 | として利用できるようになっています。 45 | 46 | 47 | 認可エンドポイント 48 | ------------------ 49 | 50 | 認可エンドポイントの実装は [AuthorizationController.cs][7] 51 | 内にあります。 52 | 53 | まずはじめに、`AuthorizationController` は Authlete の /api/auth/authorization 54 | API を呼びます。 次に、`AuthorizationController` は当 API からのレスポンスに含まれる 55 | `action` パラメーターの値をチェックし、次にとる行動を決めます。 56 | 57 | `action` が `INTERACTION` の場合、`AuthorizationController` は認可ページ (HTML) 58 | をクライアントアプリケーションに返します。 `action=INTERACTION` 59 | のときにおこなわなければならないことは、authlete-csharp の [API リファレンス][8] 60 | 内にある `AuthorizationResponse` の説明に書かれています。 61 | 62 | `action` が `NO_INTERACTION` の場合、`AuthorizationController` は 63 | `NoInteractionHandler` の `Handle()` メソッドを呼びます。 重要な点は、 64 | `NoInteractionHandler` のコンストラクターが `INoInteractionHandlerSpi` 65 | インターフェースの実装を要求することです。 66 | このインターフェースは、あなたが実装する必要のある Service Provider Interface 67 | (SPI) です。 csharp-oauth-server には簡単な例 (`NoInteractionHandlerSpiImpl`) 68 | が含まれています。 69 | 70 | `action` が `INTERACTION` でも `NO_INTERACTION` でもない場合、 71 | `AuthorizationController` は残りの仕事を `AuthorizationRequestErrorHandler` 72 | に任せます。 このハンドラーは SPI を要求しません。 73 | 74 | 75 | 認可ページ 76 | ---------- 77 | 78 | `AuthorizationController` は認可ページを手作業で描画し、クライアントアプリケーションに返します。 79 | `Views/Authorization/Page.cshtml` がビューとして、`Models/AuthorizationPageModel.cs` 80 | がモデルとして使用されます。 81 | 82 | csharp-oauth-server の認可サーバーの実装は単純ですが、変更したいだろうと思われる点が多くあります。 83 | 下記は考慮項目の例です。 84 | 85 | #### 国際化 86 | 87 | 認可ページの国際化に際して、認可リクエストに含まれる `ui_locales` 88 | パラメーターを考慮に入れてもよいでしょう。 これは [OpenID Connect Core 1.0][9] 89 | で新たに定義されたリクエストパラメーターです。 90 | 下記は、このパラメータに関する説明を仕様から抜粋したものです。 91 | 92 | > OPTIONAL. End-User's preferred languages and scripts for the user interface, 93 | > represented as a space-separated list of BCP47 [RFC5646] language tag values, 94 | > ordered by preference. For instance, the value "fr-CA fr en" represents a 95 | > preference for French as spoken in Canada, then French (without a region 96 | > designation), followed by English (without a region designation). An error 97 | > SHOULD NOT result if some or all of the requested locales are not supported 98 | > by the OpenID Provider. 99 | 100 | `AuthorizationResponse` インスタンスの `UiLocales` プロパティーを参照することで、`ui_locales` 101 | リクエストパラメーターの値を `string` の配列として取得することができます。 102 | ただし、`UiLocales` プロパティーはサポートされている UI ロケールしか返さないので、 103 | 管理コーンソール ([Service Owner Console][10]) を使って明示的に UI 104 | ロケールを指定する必要があることに注意してください。 別の言い方をすると、`ui_locales` 105 | リクエストパラメーターがどのような値であろうとも、`UiLocales` 106 | が返す配列にはサポートしている UI ロケールしか含まれていないことが保証されています。 107 | 108 | `ui_locales` パラメーターを尊重するか否かはあなたの自由です。 109 | もちろん、認可ページの国際化は好きな方法でおこなうことができます。 110 | 111 | 112 | #### 表示モード 113 | 114 | 認可リクエストには認可ページの表示方法を指定するための `display` 115 | パラメーターが含まれることがあります。 これは [OpenID Connect Core 1.0][9] 116 | で定義された新しいパラメーターです。 117 | このリクエストパラメーターが取りうる定義済みの値は次のとおりです。 118 | 表中の説明は仕様からの抜粋です。 119 | 120 | | Value | Description | 121 | |:------|:------------| 122 | | page | The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode. | 123 | | popup | The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over. | 124 | | touch | The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface. | 125 | | wap | The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display. | 126 | 127 | `AuthorizationResponse` インスタンスの `Display` プロパティーで、`display` 128 | リクエストパラメーターの値を列挙型 `Display` のインスタンスとして取得することができます。 129 | デフォルトでは、管理コンソール ([Service Owner Console][10]) 130 | では全ての表示タイプがチェックされており、サポートしていることを示していますが、 131 | チェックをはずすことでサポートしないと宣言することもできます。 132 | サポートしていない値が `display` リクエストパラメーターに指定された場合、 133 | その認可リクエストを出したクライアントアプリケーションには `invalid_request` 134 | エラーが返されることになります。 135 | 136 | 137 | 認可決定エンドポイント 138 | ---------------------- 139 | 140 | 認可ページでエンドユーザーは、認可リクエストをおこなったクライアントアプリケーションに権限を与えるか、 141 | もしくは認可リクエストを拒否するか、どちらかを選択します。 142 | 認可サーバはその決定を受け取り、それに従ってクライアントアプリケーションに適切な応答を返せなければなりません。 143 | 144 | csharp-oauth-server は、エンドユーザーの決定を `/api/authorization/decision` で受け取ります。 145 | この文書では、当該エンドポイントを認可決定エンドポイントと呼びます。 csharp-oauth-server 146 | では、認可決定エンドポイントの実装は [AuthorizationDeisionController.cs][11] 147 | 内にあります。 148 | 149 | 最後の手順として、`AuthorizationDecisionController` は `AuthorizationRequestDecisionHandler` 150 | の `Handle()` メソッドを呼びます。 重要な点は、`AuthorizationRequestDecisionHandler` 151 | のコンストラクターが `IAuthorizationRequestDecisionHandlerSpi` 152 | インターフェースの実装を要求することです。 153 | このインターフェースは、あなたが実装する必要のある Service Provider Interface です。 154 | csharp-oauth-server には簡単な例 (`AuthorizationRequestDecisionHandlerSpiImpl`) 155 | が含まれています。 156 | 157 | 158 | #### エンドユーザー認証 159 | 160 | 設計により、エンドユーザーをどのように認証するかについては、Authlete は全く気にしません。 161 | その代わりに、Authlete は認証されたエンドユーザーのサブジェクトを要求します。 162 | 163 | 「サブジェクト」はアイデンティティー関連分野の専門用語で、一意識別子のことを意味します。 164 | 典型的には、エンドユーザーのサブジェクトは、 165 | ユーザーデータベース内のプライマリーキーカラムもしくは他のユニークカラムの値です。 166 | 167 | エンドユーザーがクライアントアプリケーションに権限を与えたときは、そのエンドユーザーのサブジェクトを 168 | Authlete に伝える必要があります。 `AuthorizationRequestDecisionhandlerSpi` 169 | インターフェースの文脈では、次のように表現することができます: 170 | _「もしも `IsClientAuthorized()` が `true` を返すのであれば、そのときは 171 | `GetUserSubject()` はエンドユーザーのサブジェクトを返さなければならない。」_ 172 | 173 | エンドユーザー認証のため、csharp-oauth-server には `UserDao` クラスと `UserEntity` 174 | クラスがあります。この二つのクラスでダミーのユーザーデータベースを構成しています。 175 | もちろん、実際のユーザーデータベースを参照するためには、これらをあなたの実装で置き換える必要があります。 176 | 177 | 178 | トークンエンドポイント 179 | ---------------------- 180 | 181 | トークンエンドポイントの実装は [TokenController.cs][12] 内にあります。 182 | 183 | `TokenController` は `TokenRequestHandler` クラスを使い、トークンリクエストの処理を当クラスの 184 | `Handle()` メソッドに任せます。 重要な点は、`TokenRequestHandler` のコンストラクターが 185 | `ITokenRequestHandlerSpi` インターフェースの実装を要求することです。 186 | このインターフェースは、あなたが実装する必要のある Service Provider Interface です。 187 | csharp-oauth-server には簡単な例 (`TokenRequestHandlerSpi`) が含まれています。 188 | 189 | `ITokenRequestHandlerSpi` の `AuthenticateUser` メソッドはエンドユーザーを認証するのにしようされます。 190 | しかし、このメソッドが呼ばれるのはトークンリクエストの認可タイプが 191 | [Resource Owner Password Credentials][13] の場合のみです。 192 | そのため、この認可タイプをサポートしないのであれば、メソッドの実装は空でかまいません。 193 | 194 | 195 | イントロスペクションエンドポイント 196 | ---------------------------------- 197 | 198 | イントロスペクションエンドポイントの実装は [IntrospectionController.cs][14] 199 | 内にあります。 200 | 201 | [RFC 7662][15] (OAuth 2.0 Token Introspection) 202 | は、イントロスペクションエンドポイントを何らかの方法で保護することを要求しています。 203 | `IntrospectionController.cs` 204 | 内の保護の実装はデモンストレーション用のものであり、本番環境での利用には向かないので、適宜変更してください。 205 | 206 | 207 | コンタクト 208 | ---------- 209 | 210 | | 目的 | メールアドレス | 211 | |:-----|:---------------------| 212 | | 一般 | info@authlete.com | 213 | | 営業 | sales@authlete.com | 214 | | 広報 | pr@authlete.com | 215 | | 技術 | support@authlete.com | 216 | 217 | 218 | [1]: https://www.authlete.com/ 219 | [2]: https://tools.ietf.org/html/rfc6749 220 | [3]: https://openid.net/connect/ 221 | [4]: https://docs.authlete.com/ 222 | [5]: https://github.com/authlete/authlete-csharp 223 | [6]: https://www.nuget.org/packages/Authlete.Authlete 224 | [7]: AuthorizationServer/Controllers/AuthorizationController.cs 225 | [8]: https://authlete.github.io/authlete-csharp/ 226 | [9]: https://openid.net/specs/openid-connect-core-1_0.html 227 | [10]: https://www.authlete.com/documents/so_console/ 228 | [11]: AuthorizationServer/Controllers/AuthorizationDecisionController.cs 229 | [12]: AuthorizationServer/Controllers/TokenController.cs 230 | [13]: https://tools.ietf.org/html/rfc6749#section-4.3 231 | [14]: AuthorizationServer/Controllers/IntrospectionController.cs 232 | [15]: https://tools.ietf.org/html/rfc7662 233 | -------------------------------------------------------------------------------- /CUSTOMIZATION.md: -------------------------------------------------------------------------------- 1 | Customization 2 | ============= 3 | 4 | This document describes how to customize this authorization server 5 | implementation. 6 | 7 | 8 | Overview 9 | -------- 10 | 11 | This authorization server implementation uses [Authlete][1] as its backend. 12 | What this means are (1) that the core part of the implementation of [OAuth 13 | 2.0][2] and [OpenID Connect][3] is not in the source tree of csharp-oauth-server 14 | but in the Authlete server on cloud, and (2) that authorization data such as 15 | access tokens, settings of the authorization server itself and settings of 16 | client applications are not stored in any local database but in the database 17 | on cloud. Therefore, to put it very simply, this implementation is just an 18 | intermediary between client applications and Authlete server as illustrated 19 | below. 20 | 21 | ``` 22 | +--------+ +---------------------+ +----------+ 23 | | | | | | | 24 | | Client | <------> | csharp-oauth-server | <------> | Authlete | 25 | | | | | | | 26 | +--------+ +---------------------+ +----------+ 27 | ``` 28 | 29 | However, because Authlete focuses on **authorization** and does NOT do 30 | anything about end-user **authentication**, functions related to 31 | authentication are implemented in the source tree of csharp-oauth-server. 32 | 33 | Therefore, at least, you must customize parts related to end-user authentication. 34 | On the other hand, customization of other parts such as UI design of the 35 | authorization page is optional. 36 | 37 | 38 | Overall Structure 39 | ----------------- 40 | 41 | Authlete provides [Web APIs][4] that can be used to write an authorization 42 | server. [authlete-csharp][5] is a library which contains `IAuthleteApi` 43 | interface and its implementation to communicates with the Authlete Web APIs 44 | directly. It also contains utility classes which wraps `IAuthleteApi` in 45 | order to make it much easier for developers to implement an authorization 46 | server than calling Authlete APIs directly. 47 | 48 | [authlete-csharp][5] is available as a NuGet package, [Authlete.Authlete][6]. 49 | 50 | 51 | Authorization Endpoint 52 | ---------------------- 53 | 54 | The implementation of the authorization endpoint is in 55 | [AuthorizationController.cs][7]. 56 | 57 | First, `AuthorizationController` calls Authlete's /api/auth/authorization 58 | API. Next, `AuthorizationController` checks the value of the `action` parameter 59 | in the response from the API and decides the next action to take. 60 | 61 | When `action` is `INTERACTION`, `AuthorizationController` returns an 62 | authorization page (HTML) to the client application. What has to be done in 63 | the case of `action=INTERACTION` is described in the description of 64 | `AuthorizationResponse` in the [API reference][8] of authlete-csharp. 65 | 66 | When `action` is `NO_INTERACTION`, `AuthorizationController` calls `Handle()` 67 | method of `NoInteractionHandler`. The important point is that the constructor 68 | of `NoInteractionHandler` requires an implementation of `INoInteractionHandlerSpi` 69 | interface. The interface is the Service Provider Interface (SPI) that you need 70 | to implement. csharp-oauth-server includes a simple example 71 | (`NoInteractionHandlerSpiImpl`). 72 | 73 | When `action` is neither `INTERACTION` nor `NO_INTERACTION`, 74 | `AuthorizationController` delegates the remaining tasks to 75 | `AuthorizationRequestErrorHandler`. The handler does not require any SPI. 76 | 77 | 78 | Authorization Page 79 | ------------------ 80 | 81 | `AuthorizationController` manually renders an authorization page and returns 82 | it to the client application. `Views/Authorization/Page.cshtml` is used as 83 | the view and `Models/AuthorizationPageModel.cs` is used as the model class. 84 | 85 | The implementation of the authorization page in csharp-oauth-server is 86 | simple, but there exist many other things you may want to change. Following 87 | are some consideration points. 88 | 89 | 90 | #### Internationalization 91 | 92 | For the internationalization of the authorization page, you may take 93 | `ui_locales` parameter into consideration which may be contained in an 94 | authorization request. It is a new request parameter defined in [OpenID 95 | Connect Core 1.0][9]. The following is the description about the parameter 96 | excerpted from the specification. 97 | 98 | > OPTIONAL. End-User's preferred languages and scripts for the user interface, 99 | > represented as a space-separated list of BCP47 [RFC5646] language tag values, 100 | > ordered by preference. For instance, the value "fr-CA fr en" represents a 101 | > preference for French as spoken in Canada, then French (without a region 102 | > designation), followed by English (without a region designation). An error 103 | > SHOULD NOT result if some or all of the requested locales are not supported 104 | > by the OpenID Provider. 105 | 106 | You can get the value of `ui_locales` request paremeter as a `string` array 107 | by referring to `UiLocales` property of `AuthorizationResponse` instance. 108 | Note that, however, you have to explicitly specify which UI locales to 109 | support using the management console ([Service Owner Console][10]) because 110 | `UiLocales` property returns only supported UI locales. In other words, 111 | it is ensured that the array returned by `UiLocales` never contains 112 | unsupported UI locales whatever `ui_locales` request parameter contains. 113 | 114 | It is up to you whether to honor `ui_locales` parameter or not. Of course, 115 | you may use any means you like to internationalize the authorization page. 116 | 117 | 118 | #### Display type 119 | 120 | An authorization request may contain `display` request parameter to specify 121 | how to display the authorization page. It is a new request parameter defined 122 | in [OpenID Connect Core 1.0][9]. The predefined values of the request 123 | parameter are as follows. The descriptions in the table are excerpts from 124 | the specification. 125 | 126 | | Value | Description | 127 | |:------|:------------| 128 | | page | The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode. | 129 | | popup | The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over. | 130 | | touch | The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface. | 131 | | wap | The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display. | 132 | 133 | You can get the value of `display` request parameter as an instance of 134 | `Display` enum by referring to `Display` property or `AuthorizationResponse` 135 | instance. By default, all the display types are checked as supported in the 136 | management console ([Service Owner Console][10]), but you can uncheck them 137 | to declare some values are not supported. If an unsupported value is 138 | specified as the value of `display` request parameter, it will result in 139 | returning an `invalid_request` error to the client application that made 140 | the authorization request. 141 | 142 | 143 | Authorization Decision Endpoint 144 | ------------------------------- 145 | 146 | In an authorization page, an end-user decides either to grant permissions to 147 | the client application which made the authorization request or to deny the 148 | authorization request. An authorization server must be able to receive the 149 | decision and return a proper response to the client application according to 150 | the decision. 151 | 152 | csharp-oauth-server receives the end-user's decision at 153 | `/api/authorization/decision`. In this document, we call the endpoint 154 | _authorization decision endpoint_. In csharp-oauth-server, the implementation 155 | of the authorization decision endpoint is in 156 | [AuthorizationDecisionController.cs][11]. 157 | 158 | As the final step, `AuthorizationDecisionController` calls `Handle()` method 159 | of `AuthorizationRequestDecisionHandler`. The important point is that the 160 | constructor of `AuthorizationRequestDecisionHandler` requires an implementation 161 | of `IAuthorizationRequestDecisionHandlerSpi` interface. The interface is the 162 | Service Provider Interface that you need to implement. csharp-oauth-server 163 | includes a simple example (`AuthorizationRequestDecisionHandlerSpiImpl`). 164 | 165 | 166 | #### End-User Authentication 167 | 168 | By design, Authlete does not care about how end-users are authenticated at all. 169 | Instead, Authlete requires the subject of the authenticated end-user. 170 | 171 | _Subject_ is a technical term in the area related to identity and it means 172 | a unique identifier. In a typical case, subjects of end-users are values of 173 | the primary key column or another unique column in a user database. 174 | 175 | When an end-user grants permissions to a client application, you have to 176 | let Authlete know the subject of the end-user. In the context of 177 | `AuthorizationRequestDecisionHandlerSpi` interface, this can be described 178 | as follows: _"if `IsClientAuthorized()` returns `true`, then 179 | `GetUserSubject()` must return the subject of the end-user."_ 180 | 181 | For end-user authentication, csharp-oauth-server has `UserDao` class and 182 | `UserEntity` class. These two classes compose a dummy user database. 183 | Of course, you have to replace them with your own implementation to 184 | refer to your actual user database. 185 | 186 | 187 | Token Endpoint 188 | -------------- 189 | 190 | The implementation of the token endpoint is in [TokenController.cs][12]. 191 | 192 | `TokenController` uses `TokenRequestHandler` class and delegates the task to 193 | handle a token request to `Handle()` method of the class. The important point 194 | is that the constructor of `TokenRequestHandler` requires an implementation of 195 | `ITokenRequestHandlerSpi` interface. The interface is the Service Provider 196 | Interface that you need to implement. csharp-oauth-server includes a simple 197 | example (`TokenRequestHandlerSpiImpl`). 198 | 199 | `AuthenticateUser` method of `ITokenRequestHandlerSpi` is used to authenticate 200 | an end-user. However, the method is called only when the grant type of a token 201 | request is [Resource Owner Password Credentials][13]. Therefore, if you don't 202 | support the grant type, you can leave your implementation of the method empty. 203 | 204 | 205 | Introspection Endpoint 206 | ---------------------- 207 | 208 | The implementation of the introspection endpoint is in 209 | [IntrospectionController.cs][14]. 210 | 211 | [RFC 7662][15] (OAuth 2.0 Token Introspection) requires that the endpoint 212 | be protected in some way or other. The implementation of the protection in 213 | `IntrospectionController.cs` is for demonstration purpose only, and it is 214 | not suitable for production use. Therefore, modify the code accordingly. 215 | 216 | 217 | Contact 218 | ------- 219 | 220 | | Purpose | Email Address | 221 | |:----------|:---------------------| 222 | | General | info@authlete.com | 223 | | Sales | sales@authlete.com | 224 | | PR | pr@authlete.com | 225 | | Technical | support@authlete.com | 226 | 227 | 228 | [1]: https://www.authlete.com/ 229 | [2]: https://tools.ietf.org/html/rfc6749 230 | [3]: https://openid.net/connect/ 231 | [4]: https://docs.authlete.com/ 232 | [5]: https://github.com/authlete/authlete-csharp 233 | [6]: https://www.nuget.org/packages/Authlete.Authlete 234 | [7]: AuthorizationServer/Controllers/AuthorizationController.cs 235 | [8]: https://authlete.github.io/authlete-csharp/ 236 | [9]: https://openid.net/specs/openid-connect-core-1_0.html 237 | [10]: https://www.authlete.com/documents/so_console/ 238 | [11]: AuthorizationServer/Controllers/AuthorizationDecisionController.cs 239 | [12]: AuthorizationServer/Controllers/TokenController.cs 240 | [13]: https://tools.ietf.org/html/rfc6749#section-4.3 241 | [14]: AuthorizationServer/Controllers/IntrospectionController.cs 242 | [15]: https://tools.ietf.org/html/rfc7662 243 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.ja.md: -------------------------------------------------------------------------------- 1 | 認可サーバー実装 (C#) 2 | ===================== 3 | 4 | 概要 5 | ---- 6 | 7 | [OAuth 2.0][1] と [OpenID Connect][2] をサポートする認可サーバーの 8 | C# による実装です。 9 | 10 | この実装は、ASP.NET Core API と、NuGet パッケージ [Authlete.Authlete][4] 11 | として提供される [authlete-csharp][3] ライブラリを用いて書かれています。 12 | 13 | この実装は「DB レス」です。 これの意味するところは、認可データ 14 | (アクセストークン等) や認可サーバー自体の設定、クライアントアプリケーション群の設定を保持するためのデータベースを管理する必要がないということです。 15 | これは、[Authlete][5] をバックエンドサービスとして利用することにより実現しています。 16 | 17 | Authlete のアーキテクチャーの詳細については、 18 | *[New Architecture of OAuth 2.0 and OpenID Connect Implementation][6]* 19 | をお読みください。真のエンジニアであれば、このアーキテクチャーを気に入ってくれるはずです ;-) 20 | なお、日本語版は「[OAuth 2.0 / OIDC 実装の新アーキテクチャー][19]」です。 21 | 22 | > The primary advantage of this architecture is in that the 23 | > backend service can focus on implementing OAuth 2.0 and OpenID 24 | > Connect without caring about other components such as identity 25 | > management, user authentication, login session management, API 26 | > management and fraud detection. And, consequently, it leads to 27 | > another major advantage which enables the backend service 28 | > (implementation of OAuth 2.0 and OpenID Connect) to be combined 29 | > with any solution of other components and thus gives flexibility 30 | > to frontend server implementations. 31 | > 32 | > このアーキテクチャーの一番の利点は、アイデンティティー管理やユーザー認証、 33 | > ログインセッション管理、API 管理、不正検出などの機能について気にすることなく、 34 | > バックエンドサービスが OAuth 2.0 と OpenID Connect の実装に集中できることにあります。 35 | > この帰結として、バックエンドサービス (OAuth 2.0 と OpenID Connect の実装) 36 | > をどのような技術部品とも組み合わせることが可能というもう一つの大きな利点が得られ、 37 | > フロントエンドサーバーの実装に柔軟性がもたらされます。 38 | 39 | 40 | 41 | Please read 42 | *[New Architecture of OAuth 2.0 and OpenID Connect Implementation][6]* 43 | for details about the architecture of Authlete. 44 | True engineers will love the architecture ;-) 45 | 46 | > The primary advantage of this architecture is in that the 47 | > backend service can focus on implementing OAuth 2.0 and OpenID 48 | > Connect without caring about other components such as identity 49 | > management, user authentication, login session management, API 50 | > management and fraud detection. And, consequently, it leads to 51 | > another major advantage which enables the backend service 52 | > (implementation of OAuth 2.0 and OpenID Connect) to be combined 53 | > with any solution of other components and thus gives flexibility 54 | > to frontend server implementations. 55 | 56 | 57 | ライセンス 58 | ---------- 59 | 60 | Apache License, Version 2.0 61 | 62 | 63 | ソースコード 64 | ------------ 65 | 66 | https://github.com/authlete/csharp-oauth-server 67 | 68 | 69 | 実行方法 70 | -------- 71 | 72 | 1. この認可サーバーの実装をダウンロードします。 73 | 74 | $ git clone https://github.com/authlete/csharp-oauth-server.git 75 | $ cd csharp-oauth-server/AuthorizationServer 76 | 77 | 2. 設定ファイルを編集して API クレデンシャルズをセットします。 78 | 79 | $ vi authlete.properties 80 | 81 | 3. Start the authorization server on [http://localhost:5000][18]. 82 | 83 | $ dotnet run 84 | 85 | 86 | #### 設定ファイル 87 | 88 | `csharp-oauth-server` は `authlete.properties` を設定ファイルとして参照します。 89 | 他のファイルを使用したい場合は、次のようにそのファイルの名前を環境変数 90 | `AUTHLETE_CONFIGURATION_FILE` で指定してください。 91 | 92 | $ export AUTHLETE_CONFIGURATION_FILE=local.authlete.properties 93 | 94 | 95 | エンドポイント 96 | -------------- 97 | 98 | この実装は、下表に示すエンドポイントを公開します。 99 | 100 | | エンドポイント | パス | 101 | |:-----------------------------------|:------------------------------------| 102 | | 認可エンドポイント | `/api/authorization` | 103 | | トークンエンドポイント | `/api/token` | 104 | | JWK Set ドキュメントエンドポイント | `/api/jwks` | 105 | | 設定エンドポイント | `/.well-known/openid-configuration` | 106 | | 取り消しエンドポイント | `/api/revocation` | 107 | | イントロスペクションエンドポイント | `/api/introspection` | 108 | 109 | 認可エンドポイントとトークンエンドポイントは、[RFC 6749][1]、[OpenID Connect Core 1.0][7]、 110 | [OAuth 2.0 Multiple Response Type Encoding Practices][8]、[RFC 7636][9] ([PKCE][10])、 111 | その他の仕様で説明されているパラメーター群を受け付けます。 112 | 113 | JWK Set ドキュメントエンドポイントは、クライアントアプリケーションが 114 | (1) この OpenID プロバイダーによる署名を検証できるようにするため、また 115 | (2) この OpenID へのリクエストを暗号化できるようにするため、JSON Web 116 | Key Set ドキュメント (JWK Set) を公開します。 117 | 118 | 設定エンドポイントは、この OpenID プロバイダーの設定情報を 119 | [OpenID Connect Discovery 1.0][11] で定義されている JSON フォーマットで公開します。 120 | 121 | 取り消しエンドポイントはアクセストークンやリフレッシュトークンを取り消すための 122 | Web API です。 その動作は [RFC 7009][12] で定義されています。 123 | 124 | イントロスペクションエンドポイントはアクセストークンやリフレッシュトークンの情報を取得するための 125 | Web API です。 その動作は [RFC 7662][13] で定義されています。 126 | 127 | 128 | 認可リクエストの例 129 | ------------------ 130 | 131 | 次の例は [Implicit フロー][14]を用いて認可エンドポイントからアクセストークンを取得する例です。 132 | `{クライアントID}` となっているところは、あなたのクライアントアプリケーションの実際のクライアント 133 | ID で置き換えてください。 クライアントアプリケーションについては、[Getting Started][15] 134 | および開発者コンソールの[ドキュメント][16]を参照してください。 135 | 136 | http://localhost:5000/api/authorization?client_id={クライアントID}&response_type=token 137 | 138 | 上記のリクエストにより、認可ページが表示されます。 139 | 認可ページでは、ログイン情報の入力と、"Authorize" ボタン (認可ボタン) もしくは "Deny" ボタン 140 | (拒否ボタン) の押下が求められます。 ログイン情報として、下記のいずれかを使用してください。 141 | 142 | 143 | | ログイン ID | パスワード | 144 | |:-----------:|:----------:| 145 | | john | john | 146 | | jane | jane | 147 | 148 | もちろんこれらのログイン情報はダミーデータですので、ユーザーデータベースの実装をあなたの実装で置き換える必要があります。 149 | 150 | 151 | カスタマイズ 152 | ------------ 153 | 154 | この実装をカスタマイズする方法については [CUSTOMIZATION.ja.md][17] に記述されています。 155 | Authlete はユーザーアカウントを管理しないので、基本的には「ユーザー認証」に関わる部分についてプログラミングが必要となります。 156 | これは設計によるものです。 ユーザー認証の仕組みを実装済みの既存の Web 157 | サービスにもスムーズに OAuth 2.0 と OpenID Connect の機能を組み込めるようにするため、Authlete 158 | のアーキテクチャーは認証と認可を慎重に分離しています。 159 | 160 | 161 | その他の情報 162 | ------------ 163 | 164 | - [Authlete][5] - Authlete ホームページ 165 | - [authlete-csharp][3] - C# 用 Authlete ライブラリ 166 | - [csharp-resource-server][20] - リソースサーバーの実装 167 | 168 | 169 | コンタクト 170 | ---------- 171 | 172 | | 目的 | メールアドレス | 173 | |:-----|:---------------------| 174 | | 一般 | info@authlete.com | 175 | | 営業 | sales@authlete.com | 176 | | 広報 | pr@authlete.com | 177 | | 技術 | support@authlete.com | 178 | 179 | 180 | [1]: https://tools.ietf.org/html/rfc6749 181 | [2]: https://openid.net/connect/ 182 | [3]: https://github.com/authlete/authlete-csharp 183 | [4]: https://www.nuget.org/packages/Authlete.Authlete 184 | [5]: https://www.authlete.com/ 185 | [6]: https://medium.com/@darutk/new-architecture-of-oauth-2-0-and-openid-connect-implementation-18f408f9338d 186 | [7]: https://openid.net/specs/openid-connect-core-1_0.html 187 | [8]: https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html 188 | [9]: https://tools.ietf.org/html/rfc7636 189 | [10]: https://www.authlete.com/documents/article/pkce 190 | [11]: https://openid.net/specs/openid-connect-discovery-1_0.html 191 | [12]: https://tools.ietf.org/html/rfc7009 192 | [13]: https://tools.ietf.org/html/rfc7662 193 | [14]: https://tools.ietf.org/html/rfc6749#section-4.2 194 | [15]: https://www.authlete.com/documents/getting_started 195 | [16]: https://www.authlete.com/documents/cd_console 196 | [17]: CUSTOMIZATION.ja.md 197 | [18]: http://localhost:5000/ 198 | [19]: https://qiita.com/TakahikoKawasaki/items/b2a4fc39e0c1a1949aab 199 | [20]: https://github.com/authlete/csharp-resource-server 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Authorization Server Implementation in C# 2 | ========================================= 3 | 4 | Overview 5 | -------- 6 | 7 | This is an authorization server implementation in C# which supports 8 | [OAuth 2.0][1] and [OpenID Connect][2]. 9 | 10 | This implementation is written using ASP.NET Core API and 11 | [authlete-csharp][3] library which is provided as a NuGet package 12 | [Authlete.Authlete][4]. 13 | 14 | This implementation is _DB-less_. What this means is that you don't 15 | have to manage a database server that stores authorization data (e.g. 16 | access tokens), settings of the authorization server itself and 17 | settings of client applications. This is achieved by using 18 | [Authlete][5] as a backend service. 19 | 20 | Please read 21 | *[New Architecture of OAuth 2.0 and OpenID Connect Implementation][6]* 22 | for details about the architecture of Authlete. 23 | True engineers will love the architecture ;-) 24 | 25 | > The primary advantage of this architecture is in that the 26 | > backend service can focus on implementing OAuth 2.0 and OpenID 27 | > Connect without caring about other components such as identity 28 | > management, user authentication, login session management, API 29 | > management and fraud detection. And, consequently, it leads to 30 | > another major advantage which enables the backend service 31 | > (implementation of OAuth 2.0 and OpenID Connect) to be combined 32 | > with any solution of other components and thus gives flexibility 33 | > to frontend server implementations. 34 | 35 | 36 | License 37 | ------- 38 | 39 | Apache License, Version 2.0 40 | 41 | 42 | Source Code 43 | ----------- 44 | 45 | https://github.com/authlete/csharp-oauth-server 46 | 47 | 48 | How To Run 49 | ---------- 50 | 51 | 1. Download the source code of this authorization server implementation. 52 | 53 | $ git clone https://github.com/authlete/csharp-oauth-server.git 54 | $ cd csharp-oauth-server/AuthorizationServer 55 | 56 | 2. Edit the configuration file to set the API credentials of yours. 57 | 58 | $ vi authlete.properties 59 | 60 | 3. Start the authorization server on [http://localhost:5000][18]. 61 | 62 | $ dotnet run 63 | 64 | 65 | #### Configuration File 66 | 67 | `csharp-oauth-server` refers to `authlete.properties` as a configuration 68 | file. If you want to use another different file, specify the name of the 69 | file by the environment variable `AUTHLETE_CONFIGURATION_FILE` like the 70 | following. 71 | 72 | $ export AUTHLETE_CONFIGURATION_FILE=local.authlete.properties 73 | 74 | 75 | Endpoints 76 | --------- 77 | 78 | This implementation exposes endpoints as listed in the table below. 79 | 80 | | Endpoint | Path | 81 | |:--------------------------|:------------------------------------| 82 | | Authorization Endpoint | `/api/authorization` | 83 | | Token Endpoint | `/api/token` | 84 | | JWK Set document Endpoint | `/api/jwks` | 85 | | Configuration Endpoint | `/.well-known/openid-configuration` | 86 | | Revocation Endpoint | `/api/revocation` | 87 | | Introspection Endpoint | `/api/introspection` | 88 | 89 | The authorization endpoint and the token endpoint accept parameters 90 | described in [RFC 6749][1], [OpenID Connect Core 1.0][7], 91 | [OAuth 2.0 Multiple Response Type Encoding Practices][8], 92 | [RFC 7636][9] ([PKCE][10]) and other specifications. 93 | 94 | The JWK Set document endpoint exposes a JSON Web Key Set document 95 | (JWK Set) so that client applications can (1) verify signatures by 96 | this OpenID Provider and (2) encrypt their requests to this OpenID 97 | Provider. 98 | 99 | The configuration endpoint exposes the configuration information of 100 | this OpenID Provider in the JSON format defined in 101 | [OpenID Connect Discovery 1.0][11]. 102 | 103 | The revocation endpoint is a Web API to revoke access tokens and 104 | refresh tokens. Its behavior is defined in [RFC 7009][12]. 105 | 106 | The introspection endpoint is a Web API to get information about access 107 | tokens and refresh tokens. Its behavior is defined in [RFC 7662][13]. 108 | 109 | 110 | Authorization Request Example 111 | ----------------------------- 112 | 113 | The following is an example to get an access token from the authorization 114 | endpoint using [Implicit Flow][14]. Don't forget to replace `{client-id}` 115 | in the URL with the real client ID of one of your client applications. 116 | As for client applications, see [Getting Started][15] and the 117 | [document][16] of _Developer Console_. 118 | 119 | http://localhost:5000/api/authorization?client_id={client-id}&response_type=token 120 | 121 | The request above will show you an authorization page. The page asks 122 | you to input login credentials and click "Authorize" button or "Deny" 123 | button. Use one of the following as login credentials. 124 | 125 | | Login ID | Password | 126 | |:--------:|:--------:| 127 | | john | john | 128 | | jane | jane | 129 | 130 | Of course, these login credentials are dummy data, so you need to replace 131 | the user database implementation with your own. 132 | 133 | 134 | Customization 135 | ------------- 136 | 137 | How to customize this implementation is described in [CUSTOMIZATION.md][17]. 138 | Basically, you need to do programming for _end-user authentication_ because 139 | Authlete does not manage end-user accounts. This is by design. The 140 | architecture of Authlete carefully seperates authorization from authentication 141 | so that you can add OAuth 2.0 and OpenID Connect functionalities seamlessly 142 | into even an existing web service which may already have a mechanism for 143 | end-user authentication. 144 | 145 | 146 | See Also 147 | -------- 148 | 149 | - [Authlete][5] - Authlete Home Page 150 | - [authlete-csharp][3] - Authlete Library for C# 151 | - [csharp-resource-server][20] - Resource Server Implementation 152 | 153 | 154 | Contact 155 | ------- 156 | 157 | | Purpose | Email Address | 158 | |:----------|:---------------------| 159 | | General | info@authlete.com | 160 | | Sales | sales@authlete.com | 161 | | PR | pr@authlete.com | 162 | | Technical | support@authlete.com | 163 | 164 | 165 | [1]: https://tools.ietf.org/html/rfc6749 166 | [2]: https://openid.net/connect/ 167 | [3]: https://github.com/authlete/authlete-csharp 168 | [4]: https://www.nuget.org/packages/Authlete.Authlete 169 | [5]: https://www.authlete.com/ 170 | [6]: https://medium.com/@darutk/new-architecture-of-oauth-2-0-and-openid-connect-implementation-18f408f9338d 171 | [7]: https://openid.net/specs/openid-connect-core-1_0.html 172 | [8]: https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html 173 | [9]: https://tools.ietf.org/html/rfc7636 174 | [10]: https://www.authlete.com/documents/article/pkce 175 | [11]: https://openid.net/specs/openid-connect-discovery-1_0.html 176 | [12]: https://tools.ietf.org/html/rfc7009 177 | [13]: https://tools.ietf.org/html/rfc7662 178 | [14]: https://tools.ietf.org/html/rfc6749#section-4.2 179 | [15]: https://www.authlete.com/documents/getting_started 180 | [16]: https://www.authlete.com/documents/cd_console 181 | [17]: CUSTOMIZATION.md 182 | [18]: http://localhost:5000/ 183 | [20]: https://github.com/authlete/csharp-resource-server 184 | --------------------------------------------------------------------------------