public object Any(GetAccessToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (string.IsNullOrEmpty(request.RefreshToken)) { throw new ArgumentNullException(nameof(request.RefreshToken)); } JsonObject jwtPayload; try { jwtPayload = jwtAuthProvider.GetVerifiedJwtPayload(Request, request.RefreshToken.Split('.')); } catch (ArgumentException) { throw; } catch (Exception ex) { throw new ArgumentException(ex.Message); } jwtAuthProvider.AssertJwtPayloadIsValid(jwtPayload); if (jwtAuthProvider.ValidateRefreshToken != null && !jwtAuthProvider.ValidateRefreshToken(jwtPayload, Request)) { throw new ArgumentException(ErrorMessages.RefreshTokenInvalid.Localize(Request), nameof(request.RefreshToken)); } var userId = jwtPayload["sub"]; IAuthSession session; IEnumerable <string> roles = null, perms = null; var userSessionSource = AuthenticateService.GetUserSessionSource(); if (userSessionSource != null) { session = userSessionSource.GetUserSession(userId); if (session == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists.Localize(Request)); } roles = session.Roles; perms = session.Permissions; } else if (AuthRepository is IUserAuthRepository userRepo) { var userAuth = userRepo.GetUserAuth(userId); if (userAuth == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists.Localize(Request)); } if (jwtAuthProvider.IsAccountLocked(userRepo, userAuth)) { throw new AuthenticationException(ErrorMessages.UserAccountLocked.Localize(Request)); } session = SessionFeature.CreateNewSession(Request, SessionExtensions.CreateRandomSessionId()); jwtAuthProvider.PopulateSession(userRepo, userAuth, session); if (userRepo is IManageRoles manageRoles && session.UserAuthId != null) { roles = manageRoles.GetRoles(session.UserAuthId); perms = manageRoles.GetPermissions(session.UserAuthId); } } else { throw new NotSupportedException("JWT RefreshTokens requires a registered IUserAuthRepository or an AuthProvider implementing IUserSessionSource"); } var accessToken = jwtAuthProvider.CreateJwtBearerToken(Request, session, roles, perms); var response = new GetAccessTokenResponse { AccessToken = accessToken }; if (request.UseTokenCookie != true) { return(response); } return(new HttpResult(new GetAccessTokenResponse()) { Cookies = { new Cookie(Keywords.TokenCookie, accessToken, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
public object Any(GetAccessToken request) { var jwtAuthProvider = AuthenticateService.GetAuthProvider(JwtAuthProvider.Name) as JwtAuthProvider; if (jwtAuthProvider == null) { throw new NotSupportedException("JwtAuthProvider is not registered"); } if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection); } if (string.IsNullOrEmpty(request.RefreshToken)) { throw new ArgumentNullException(nameof(request.RefreshToken)); } var userRepo = AuthRepository as IUserAuthRepository; if (userRepo == null) { throw new NotSupportedException("JWT Refresh Tokens requires a registered IUserAuthRepository"); } var jwtPayload = jwtAuthProvider.GetVerifiedJwtPayload(request.RefreshToken.Split('.')); jwtAuthProvider.AssertJwtPayloadIsValid(jwtPayload); if (jwtAuthProvider.ValidateRefreshToken != null && !jwtAuthProvider.ValidateRefreshToken(jwtPayload, Request)) { throw new ArgumentException(ErrorMessages.RefreshTokenInvalid, nameof(request.RefreshToken)); } var userId = jwtPayload["sub"]; var userAuth = userRepo.GetUserAuth(userId); if (userAuth == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists); } if (jwtAuthProvider.IsAccountLocked(userRepo, userAuth)) { throw new AuthenticationException(ErrorMessages.UserAccountLocked); } var session = SessionFeature.CreateNewSession(Request, SessionExtensions.CreateRandomSessionId()); jwtAuthProvider.PopulateSession(userRepo, userAuth, session); IEnumerable <string> roles = null, perms = null; var manageRoles = userRepo as IManageRoles; if (manageRoles != null && session.UserAuthId != null) { roles = manageRoles.GetRoles(session.UserAuthId); perms = manageRoles.GetPermissions(session.UserAuthId); } var accessToken = jwtAuthProvider.CreateJwtBearerToken(session, roles, perms); return(new GetAccessTokenResponse { AccessToken = accessToken }); }
public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) { var tokens = Init(authService, ref session, request); //Transferring AccessToken/Secret from Mobile/Desktop App to Server if (request?.AccessToken != null && VerifyAccessToken != null) { if (!VerifyAccessToken(request.AccessToken)) { return(HttpError.Unauthorized("AccessToken is not for client_id: " + ConsumerKey)); } var isHtml = authService.Request.IsHtml(); var failedResult = AuthenticateWithAccessToken(authService, session, tokens, request.AccessToken); if (failedResult != null) { return(ConvertToClientError(failedResult, isHtml)); } return(isHtml ? authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1"))) : null); //return default AuthenticateResponse } var httpRequest = authService.Request; var error = httpRequest.QueryString["error_reason"] ?? httpRequest.QueryString["error"] ?? httpRequest.QueryString["error_code"] ?? httpRequest.QueryString["error_description"]; var hasError = !error.IsNullOrEmpty(); if (hasError) { Log.Error($"OAuth2 Error callback. {httpRequest.QueryString}"); return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.SetParam("f", error)))); } var code = httpRequest.QueryString[Keywords.Code]; var isPreAuthCallback = !code.IsNullOrEmpty(); if (!isPreAuthCallback) { var oauthstate = SessionExtensions.CreateRandomSessionId(); var preAuthUrl = AuthorizeUrl .AddQueryParam("response_type", "code") .AddQueryParam("client_id", ConsumerKey) .AddQueryParam("redirect_uri", this.CallbackUrl) .AddQueryParam("scope", string.Join(" ", Scopes)) .AddQueryParam(Keywords.State, oauthstate); if (session is AuthUserSession authSession) { (authSession.Meta ?? (authSession.Meta = new Dictionary <string, string>()))["oauthstate"] = oauthstate; } this.SaveSession(authService, session, SessionExpiry); return(authService.Redirect(PreAuthUrlFilter(this, preAuthUrl))); } try { var state = httpRequest.QueryString[Keywords.State]; if (state != null && session is AuthUserSession authSession) { if (authSession.Meta.TryGetValue("oauthstate", out var oauthState) && state != oauthState) { return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.SetParam("f", "InvalidState")))); } authSession.Meta.Remove("oauthstate"); } var contents = GetAccessTokenJson(code); var authInfo = JsonObject.Parse(contents); var accessToken = authInfo["access_token"]; return(AuthenticateWithAccessToken(authService, session, tokens, accessToken) ?? authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1")))); //Haz Access! } catch (WebException we) { string errorBody = we.GetResponseBody(); var statusCode = ((HttpWebResponse)we.Response).StatusCode; if (statusCode == HttpStatusCode.BadRequest) { return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.SetParam("f", "AccessTokenFailed")))); } } //Shouldn't get here return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.SetParam("f", "Unknown")))); }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(req, res)) { return(TypeConstants.EmptyTask); } var feature = HostContext.GetPlugin <ServerEventsFeature>(); var session = req.GetSession(); if (feature.LimitToAuthenticatedUsers && !session.IsAuthenticated) { session.ReturnFailedAuthentication(req); return(TypeConstants.EmptyTask); } res.ContentType = MimeTypes.ServerSentEvents; res.AddHeader(HttpHeaders.CacheControl, "no-cache"); res.ApplyGlobalResponseHeaders(); res.UseBufferedStream = false; res.KeepAlive = true; feature.OnInit?.Invoke(req); res.Flush(); var serverEvents = req.TryResolve <IServerEvents>(); var userAuthId = session?.UserAuthId; var anonUserId = serverEvents.GetNextSequence("anonUser"); var userId = userAuthId ?? ("-" + anonUserId); var displayName = session.GetSafeDisplayName() ?? "user" + anonUserId; var now = DateTime.UtcNow; var subscriptionId = SessionExtensions.CreateRandomSessionId(); //Handle both ?channel=A,B,C or ?channels=A,B,C var channels = new List <string>(); var channel = req.QueryString["channel"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } channel = req.QueryString["channels"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } if (channels.Count == 0) { channels = EventSubscription.UnknownChannel.ToList(); } var subscription = new EventSubscription(res) { CreatedAt = now, LastPulseAt = now, Channels = channels.ToArray(), SubscriptionId = subscriptionId, UserId = userId, UserName = session != null ? session.UserName : null, DisplayName = displayName, SessionId = req.GetSessionId(), IsAuthenticated = session != null && session.IsAuthenticated, UserAddress = req.UserHostAddress, OnPublish = feature.OnPublish, //OnError = feature.OnError, Meta = { { "userId", userId }, { "displayName", displayName }, { "channels", string.Join(",", channels) }, { AuthMetadataProvider.ProfileUrlKey, session.GetProfileUrl() ?? AuthMetadataProvider.DefaultNoProfileImgUrl }, } }; feature.OnCreated?.Invoke(subscription, req); if (req.Response.IsClosed) { return(TypeConstants.EmptyTask); //Allow short-circuiting in OnCreated callback } var heartbeatUrl = feature.HeartbeatPath != null ? req.ResolveAbsoluteUrl("~/".CombineWith(feature.HeartbeatPath)).AddQueryParam("id", subscriptionId) : null; var unRegisterUrl = feature.UnRegisterPath != null ? req.ResolveAbsoluteUrl("~/".CombineWith(feature.UnRegisterPath)).AddQueryParam("id", subscriptionId) : null; heartbeatUrl = AddSessionParamsIfAny(heartbeatUrl, req); unRegisterUrl = AddSessionParamsIfAny(unRegisterUrl, req); subscription.ConnectArgs = new Dictionary <string, string>(subscription.Meta) { { "id", subscriptionId }, { "unRegisterUrl", unRegisterUrl }, { "heartbeatUrl", heartbeatUrl }, { "updateSubscriberUrl", req.ResolveAbsoluteUrl("~/event-subscribers/" + subscriptionId) }, { "heartbeatIntervalMs", ((long)feature.HeartbeatInterval.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) }, { "idleTimeoutMs", ((long)feature.IdleTimeout.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) } }; feature.OnConnect?.Invoke(subscription, subscription.ConnectArgs); serverEvents.Register(subscription, subscription.ConnectArgs); var tcs = new TaskCompletionSource <bool>(); subscription.OnDispose = _ => { try { res.EndHttpHandlerRequest(skipHeaders: true); } catch { } tcs.SetResult(true); }; return(tcs.Task); }