Esempio n. 1
0
        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),
                    }
                }
            });
        }
Esempio n. 2
0
        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
            });
        }
Esempio n. 3
0
        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"))));
        }
Esempio n. 4
0
        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);
        }