public ActionResult Create(Client client)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    this.clientRepository.Create(client);
                    TempData["Message"] = Resources.OAuthClientController.ClientCreated;
                    return RedirectToAction("Edit", new { id = client.ID });
                }
                catch (ValidationException ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
                catch (Exception)
                {
                    ModelState.AddModelError("", Resources.OAuthClientController.ErrorCreatingClient);
                }
            }

            return Edit(client.ID);
        }
        private ActionResult PerformImplicitGrant(AuthorizeRequest request, Client client)
        {
            var sts = new STS();

            TokenResponse tokenResponse;
            if (sts.TryIssueToken(
                new EndpointReference(request.scope),
                ClaimsPrincipal.Current,
                Configuration.Global.DefaultHttpTokenType,
                out tokenResponse))
            {
                var tokenString = string.Format("access_token={0}&token_type={1}&expires_in={2}",
                    tokenResponse.AccessToken,
                    tokenResponse.TokenType,
                    tokenResponse.ExpiresIn);

                if (!string.IsNullOrEmpty(request.state))
                {
                    tokenString = string.Format("{0}&state={1}", tokenString, Server.UrlEncode(request.state));
                }

                var redirectString = string.Format("{0}#{1}",
                    client.RedirectUri.AbsoluteUri,
                    tokenString);

                return Redirect(redirectString);
            }

            // return right error code
            return ClientError(client.RedirectUri, OAuth2Constants.Errors.InvalidRequest, request.response_type,
                request.state);
        }
        private ActionResult PerformGrant(AuthorizeRequest request, Client client)
        {
            // implicit grant
            if (request.response_type.Equals(OAuth2Constants.ResponseTypes.Token, StringComparison.Ordinal))
            {
                return PerformImplicitGrant(request, client);
            }

            // authorization code grant
            if (request.response_type.Equals(OAuth2Constants.ResponseTypes.Code, StringComparison.Ordinal))
            {
                return PerformAuthorizationCodeGrant(request, client);
            }

            return null;
        }
        private ActionResult PerformAuthorizationCodeGrant(AuthorizeRequest request, Client client)
        {
            var code = CodeTokenRepository.AddCode(CodeTokenType.AuthorizationCode, client.ID,
                ClaimsPrincipal.Current.Identity.Name, request.scope);
            var tokenString = string.Format("code={0}", code);

            if (!string.IsNullOrEmpty(request.state))
            {
                tokenString = string.Format("{0}&state={1}", tokenString, Server.UrlEncode(request.state));
            }

            var redirectString = string.Format("{0}?{1}",
                client.RedirectUri.AbsoluteUri,
                tokenString);

            return Redirect(redirectString);
        }
        private ActionResult CheckRequest(AuthorizeRequest request, out Client client)
        {
            if (request == null)
            {
                client = null;
                ViewBag.Message = "Invalid request parameters";
                Tracing.Error(ViewBag.Message);
                return View("Error");
            }

            // validate client
            if (!Clients.TryGetClient(request.client_id, out client))
            {
                ViewBag.Message = "Invalid client_id : " + request.client_id;
                Tracing.Error(ViewBag.Message);
                return View("Error");
            }

            // validate redirect uri
            if (client.RedirectUri == null)
            {
                ViewBag.Message = "A redirect uri for client_id " + request.client_id + " was not configured.";
                Tracing.Error(ViewBag.Message);
                return View("Error");
            }

            if (string.IsNullOrEmpty(request.redirect_uri) ||
                !string.Equals(request.redirect_uri, client.RedirectUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase))
            {
                ViewBag.Message = "The redirect_uri in the request: " + request.redirect_uri +
                                  " did not match a registered redirect URI.";
                Tracing.Error(ViewBag.Message);
                return View("Error");
            }

            Uri redirectUrl;
            if (Uri.TryCreate(request.redirect_uri, UriKind.Absolute, out redirectUrl))
            {
                if (redirectUrl.Scheme == Uri.UriSchemeHttp)
                {
                    Tracing.Error("Redirect URI not over SSL : " + request.redirect_uri);
                    return ClientError(client.RedirectUri, OAuth2Constants.Errors.InvalidRequest, string.Empty,
                        request.state);
                }
            }
            else
            {
                Tracing.Error("Redirect URI not a valid URI : " + request.redirect_uri);
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.InvalidRequest, string.Empty,
                    request.state);
            }

            if (string.IsNullOrWhiteSpace(request.response_type))
            {
                Tracing.Error("response_type is null or empty");
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.InvalidRequest, string.Empty,
                    request.state);
            }

            // check response type (only code and token are supported)
            if (!request.response_type.Equals(OAuth2Constants.ResponseTypes.Token, StringComparison.Ordinal) &&
                !request.response_type.Equals(OAuth2Constants.ResponseTypes.Code, StringComparison.Ordinal))
            {
                Tracing.Error("response_type is not token or code: " + request.response_type);
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.UnsupportedResponseType, string.Empty,
                    request.state);
            }

            // validate scope (must be a valid URI)
            Uri uri;
            if (!Uri.TryCreate(request.scope, UriKind.Absolute, out uri))
            {
                Tracing.Error("scope is not a URI: " + request.scope);
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.InvalidScope, request.response_type,
                    request.state);
            }

            // validate if request grant type is allowed for client (implicit vs code flow)
            if (request.response_type.Equals(OAuth2Constants.ResponseTypes.Token) &&
                !client.AllowImplicitFlow)
            {
                Tracing.Error("response_type is token and client does not allow implicit flow. client: " + client.Name);
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.UnsupportedResponseType,
                    request.response_type, request.state);
            }

            if (request.response_type.Equals(OAuth2Constants.ResponseTypes.Code) &&
                !client.AllowCodeFlow)
            {
                Tracing.Error("response_type is code and client does not allow code flow. client: " + client.Name);
                return ClientError(client.RedirectUri, OAuth2Constants.Errors.UnsupportedResponseType,
                    request.response_type, request.state);
            }

            return null;
        }
        public ActionResult Edit(int? id)
        {
            Client client = null;
            if (id != null && id > 0)
            {
                client = this.clientRepository.Get(id.Value);
                if (client == null) return HttpNotFound();
            }
            else
            {
                client = new Client();
            }

            var vm = new OAuthClientViewModel(client);
            return View("Edit", vm);
        }
        private bool ValidateClient(out Client client)
        {
            client = null;

            if (!ClaimsPrincipal.Current.Identity.IsAuthenticated)
            {
                Tracing.Error("Anonymous client.");
                return false;
            }

            var passwordClaim = ClaimsPrincipal.Current.FindFirst("password");
            if (passwordClaim == null)
            {
                Tracing.Error("No client secret provided.");
                return false;
            }

            return ClientsRepository.ValidateAndGetClient(
                ClaimsPrincipal.Current.Identity.Name,
                passwordClaim.Value,
                out client);
        }
        private HttpResponseMessage ValidateRequest(TokenRequest request, out Client client)
        {
            client = null;

            if (request == null)
            {
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest);
            }

            // grant type is required
            if (string.IsNullOrWhiteSpace(request.Grant_Type))
            {
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType);
            }

            // check supported grant types
            if (!request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode) &&
                !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password) &&
                !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken))
            {
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType);
            }

            // resource owner password flow requires a well-formed scope
            if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password))
            {
                Uri appliesTo;
                if (!Uri.TryCreate(request.Scope, UriKind.Absolute, out appliesTo))
                {
                    Tracing.Error("Malformed scope: " + request.Scope);
                    return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope);
                }

                Tracing.Information("OAuth2 endpoint called for scope: " + request.Scope);
            }

            if (!ValidateClient(out client))
            {
                Tracing.Error("Invalid client: " + ClaimsPrincipal.Current.Identity.Name);
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidClient);
            }

            // validate grant types against global and client configuration
            if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode))
            {
                if (!ConfigurationRepository.OAuth2.EnableCodeFlow ||
                    !client.AllowCodeFlow)
                {
                    Tracing.Error("Code flow not allowed for client");
                    return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType);
                }
            }

            if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password))
            {
                if (!ConfigurationRepository.OAuth2.EnableResourceOwnerFlow ||
                    !client.AllowResourceOwnerFlow)
                {
                    Tracing.Error("Resource owner password flow not allowed for client");
                    return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType);
                }
            }

            if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken))
            {
                if (!client.AllowRefreshToken)
                {
                    Tracing.Error("Refresh tokens not allowed for client");
                    return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType);
                }
            }

            return null;
        }
        private HttpResponseMessage ProcessResourceOwnerCredentialRequest(TokenRequest request, string tokenType,
            Client client)
        {
            Tracing.Information("Starting resource owner password credential flow for client: " + client.Name);
            var appliesTo = new EndpointReference(request.Scope);

            if (string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password))
            {
                Tracing.Error("Invalid resource owner credentials for: " + appliesTo.Uri.AbsoluteUri);
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant);
            }

            if (UserRepository.ValidateUser(request.UserName, request.Password))
            {
                return CreateTokenResponse(request.UserName, client, appliesTo, tokenType, client.AllowRefreshToken);
            }
            Tracing.Error("Resource owner credential validation failed: " + request.UserName);
            return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant);
        }
 private HttpResponseMessage ProcessRefreshTokenRequest(Client client, string refreshToken, string tokenType)
 {
     Tracing.Information("Processing refresh token request for client: " + client.Name);
     return ProcessCodeTokenRequest(client, refreshToken, tokenType);
 }
        private HttpResponseMessage ProcessCodeTokenRequest(Client client, string codeToken, string tokenType)
        {
            // 1. get code token from DB - if not exists: error
            CodeToken token;
            if (CodeTokenRepository.TryGetCode(codeToken, out token))
            {
                CodeTokenRepository.DeleteCode(token.Code);

                // 2. make sure the client is the same - if not: error
                if (token.ClientId == client.ID)
                {
                    // 3. call STS
                    return CreateTokenResponse(token.UserName, client, new EndpointReference(token.Scope), tokenType,
                        client.AllowRefreshToken);
                }

                Tracing.Error("Invalid client for refresh token. " + client.Name + " / " + codeToken);
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant);
            }

            Tracing.Error("Refresh token not found. " + client.Name + " / " + codeToken);
            return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant);
        }
 private HttpResponseMessage ProcessAuthorizationCodeRequest(Client client, string code, string tokenType)
 {
     Tracing.Information("Processing authorization code token request for client: " + client.Name);
     return ProcessCodeTokenRequest(client, code, tokenType);
 }
        private HttpResponseMessage CreateTokenResponse(string userName, Client client, EndpointReference scope,
            string tokenType, bool includeRefreshToken)
        {
            var auth = new AuthenticationHelper();

            var principal = auth.CreatePrincipal(userName, "OAuth2",
                new[]
                {
                    new Claim(Constants.Claims.Client, client.Name),
                    new Claim(Constants.Claims.Scope, scope.Uri.AbsoluteUri)
                });

            if (!ClaimsAuthorization.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.OAuth2))
            {
                Tracing.Error("OAuth2 endpoint authorization failed for user: " + userName);
                return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant);
            }

            var sts = new STS();
            TokenResponse tokenResponse;
            if (sts.TryIssueToken(scope, principal, tokenType, out tokenResponse))
            {
                if (includeRefreshToken)
                {
                    tokenResponse.RefreshToken = CodeTokenRepository.AddCode(CodeTokenType.RefreshTokenIdentifier,
                        client.ID, userName, scope.Uri.AbsoluteUri);
                }

                var resp = Request.CreateResponse(HttpStatusCode.OK, tokenResponse);
                return resp;
            }
            return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest);
        }