public void Verify(IHttpContext context, JObject authToken, out ApiUser user) { SteamApiUser steamUser = authToken.ToObject <SteamApiUser>(); if (steamUser == null) { throw new ForbiddenException(); } user = steamUser; ApiUser.VerifyUser(steamUser, context); var allowedSteamIds = Config.Instance.SteamAuthentication.AllowedSteamIds; if (allowedSteamIds.Length > 0 && !allowedSteamIds.Contains(steamUser.SteamID)) { Logging.Log( new Dictionary <string, string>() { { "SteamID", steamUser.SteamID } }, "JWT login request contained a SteamID not in the allow list." ); throw new ForbiddenException(); } }
public static SteamApiUser MakeSteamUser(IHttpContext context, ulong steamId) { var user = new SteamApiUser { SteamID = steamId.ToString() }; ApiUser.InitializeUser(user, context); return(user); }
public async Task <ApiUser> TryAuthenticate(IHttpContext context) { if (!Config.Instance.SteamAuthentication.Enabled) { throw new NotFoundException(); } if (context.Request.Method != "GET") { // openid requests use GET throw new MethodNotAllowedException(); } var queryString = context.Request.QueryString; if (queryString.Count == 0) { // Redirect to steam's openid endpoint var queryParams = new Dictionary <string, string>() { { "openid.ns", "http://specs.openid.net/auth/2.0" }, { "openid.mode", "checkid_setup" }, // Normally, we would have the response come back to us, but we are using jwt and not session data. // This means the client has to make the call to us, not steam, as the client will need to receive the // resulting authorization header. // These are left blank, and the client must fill them in on its own. //{"openid.return_to", string.Format("{0}://{1}:{2}/login", Config.Protocol, Server.IP, Config.Port)}, //{"openid.realm", string.Format("{0}://{1}:{2}", Config.Protocol, Server.IP, Config.Port)}, { "openid.identity", "http://specs.openid.net/auth/2.0/identifier_select" }, { "openid.claimed_id", "http://specs.openid.net/auth/2.0/identifier_select" } }; var query = GenerateQuery(queryParams); // Would be nice to use TemporarilyMoved here, but thats auto handled by browsers // and there is no way for the client to receive the location being redirected. // context.Response.Headers.Add("Location", string.Format("{0}?{1}", ProviderUri, query)); await context.SendResponse(Ceen.HttpStatusCode.OK, new AuthenticateWithSteamPayload() { location = string.Format("{0}?{1}", ProviderUri, query) }); return(null); } queryString["openid.mode"] = "check_authentication"; var responseString = HttpPost(ProviderUri, GenerateQuery(queryString)); var match = SteamIdRegex.Match(queryString["openid.claimed_id"]); ulong steamId = ulong.Parse(match.Groups[1].Value); match = IsValidRegex.Match(responseString); var isValid = match.Success; if (!isValid) { Logging.Log( new Dictionary <string, string>() { { "SteamID", steamId.ToString() } }, "Steam rejected the provided openid credentials." ); throw new ForbiddenException("Invalid Credentials."); } var allowedSteamIds = Config.Instance.SteamAuthentication.AllowedSteamIds; if (allowedSteamIds.Length > 0 && !allowedSteamIds.Contains(steamId.ToString())) { Logging.Log( new Dictionary <string, string>() { { "SteamID", steamId.ToString() } }, "Attempted login by a SteamID not in the allow list." ); throw new ForbiddenException(); } var user = SteamApiUser.MakeSteamUser(context, steamId); Authenticator.SetUserToken(context, user); return(user); }