/// <summary> /// Verifies the Character information for the provided Token information. /// While this method represents the oauth/verify request, in addition to the verified data that ESI returns, this object also stores the Token and Refresh token /// and this method also uses ESI retrieves other information pertinent to making calls in the ESI.NET API. (alliance_id, corporation_id, faction_id) /// You will need a record in your database that stores at least this information. Serialize and store this object for quick retrieval and token refreshing. /// </summary> /// <param name="token"></param> /// <returns></returns> public async Task <AuthorizedCharacterData> Verify(SsoToken token) { _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken); var response = await _client.GetAsync($"{_ssoUrl}/oauth/verify").Result.Content.ReadAsStringAsync(); var authorizedCharacter = JsonConvert.DeserializeObject <AuthorizedCharacterData>(response); authorizedCharacter.Token = token.AccessToken; authorizedCharacter.RefreshToken = token.RefreshToken; var url = $"{_config.EsiUrl}v1/characters/affiliation/?datasource={_config.DataSource.ToEsiValue()}"; var body = new StringContent(JsonConvert.SerializeObject(new int[] { authorizedCharacter.CharacterID }), Encoding.UTF8, "application/json"); // Get more specifc details about authorized character to be used in API calls that require this data about the character var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken); var characterResponse = await client.PostAsync(url, body).ConfigureAwait(false); if (characterResponse.StatusCode == System.Net.HttpStatusCode.OK) { EsiResponse <List <Affiliation> > affiliations = new EsiResponse <List <Affiliation> >(characterResponse, "Post|/character/affiliations/", "v1"); var characterData = affiliations.Data.First(); authorizedCharacter.AllianceID = characterData.AllianceId; authorizedCharacter.CorporationID = characterData.CorporationId; authorizedCharacter.FactionID = characterData.FactionId; } return(authorizedCharacter); }
// Returns an enum representation of why the fleet members api errored public static FleetErrorType?ErrorType(this ESI.NET.EsiResponse <List <ESI.NET.Models.Fleets.Wing> > x) { if (x.Message.Contains("The specified proxy or server node") && x.Message.Contains("is dead")) { return(FleetErrorType.FleetDead); } if (x.Message.Contains("The fleet does not exist or you don't have access to it")) { return(FleetErrorType.InvalidBoss); } return(null); }
/// <summary> /// Verifies the Character information for the provided Token information. /// While this method represents the oauth/verify request, in addition to the verified data that ESI returns, this object also stores the Token and Refresh token /// and this method also uses ESI retrieves other information pertinent to making calls in the ESI.NET API. (alliance_id, corporation_id, faction_id) /// You will need a record in your database that stores at least this information. Serialize and store this object for quick retrieval and token refreshing. /// </summary> /// <param name="token"></param> /// <returns></returns> public async Task <AuthorizedCharacterData> Verify(SsoToken token) { AuthorizedCharacterData authorizedCharacter = new AuthorizedCharacterData(); try { var tokenHandler = new JwtSecurityTokenHandler(); // Get the eve online JWT to validate against var jwtksUrl = $"https://{_ssoUrl}/oauth/jwks"; var response = await _client.GetAsync(jwtksUrl).Result.Content.ReadAsStringAsync(); var jwks = new JsonWebKeySet(response); var jwk = jwks.Keys.First(); SecurityToken validatedToken; // Validate the token TokenValidationParameters tokenValidationParams = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = true, ValidIssuer = _ssoUrl, ValidateIssuerSigningKey = true, IssuerSigningKey = jwk, ClockSkew = TimeSpan.FromSeconds(2), // CCP's servers seem slightly ahead (~1s) }; tokenHandler.ValidateToken(token.AccessToken, tokenValidationParams, out validatedToken); JwtSecurityToken jwtValidatedToken = validatedToken as JwtSecurityToken; var subjectClaim = jwtValidatedToken.Claims.SingleOrDefault(c => c.Type == "sub").Value; var nameClaim = jwtValidatedToken.Claims.SingleOrDefault(c => c.Type == "name").Value; var ownerClaim = jwtValidatedToken.Claims.SingleOrDefault(c => c.Type == "owner").Value; var returnedScopes = jwtValidatedToken.Claims.Where(c => c.Type == "scp"); var scopesClaim = string.Join(" ", returnedScopes.Select(s => s.Value)); authorizedCharacter.RefreshToken = token.RefreshToken; authorizedCharacter.Token = token.AccessToken; authorizedCharacter.CharacterName = nameClaim; authorizedCharacter.CharacterOwnerHash = ownerClaim; authorizedCharacter.CharacterID = int.Parse(subjectClaim.Split(':').Last()); authorizedCharacter.ExpiresOn = jwtValidatedToken.ValidTo; authorizedCharacter.Scopes = scopesClaim; // Get more specifc details about authorized character to be used in API calls that require this data about the character var url = $"{_config.EsiUrl}latest/characters/affiliation/?datasource={_config.DataSource.ToEsiValue()}"; var body = new StringContent(JsonConvert.SerializeObject(new int[] { authorizedCharacter.CharacterID }), Encoding.UTF8, "application/json"); var client = new HttpClient(); var characterResponse = await client.PostAsync(url, body).ConfigureAwait(false); if (characterResponse.StatusCode == HttpStatusCode.OK) { EsiResponse <List <Affiliation> > affiliations = new EsiResponse <List <Affiliation> >(characterResponse, "Post|/character/affiliations/"); var characterData = affiliations.Data.First(); authorizedCharacter.AllianceID = characterData.AllianceId; authorizedCharacter.CorporationID = characterData.CorporationId; authorizedCharacter.FactionID = characterData.FactionId; } } catch { // validation failed } return(authorizedCharacter); }
public static async Task <EsiResponse <T> > Execute <T>(HttpClient client, EsiConfig config, RequestSecurity security, RequestMethod method, string endpoint, Dictionary <string, string> replacements = null, string[] parameters = null, object body = null, string token = null) { client.DefaultRequestHeaders.Clear(); var path = $"{method.ToString()}|{endpoint}"; var version = EndpointVersion[path]; if (replacements != null) { foreach (var property in replacements) { endpoint = endpoint.Replace($"{{{property.Key}}}", property.Value); } } var url = $"{config.EsiUrl}{version}{endpoint}?datasource={config.DataSource.ToEsiValue()}"; //Attach token to request header if this endpoint requires an authorized character if (security == RequestSecurity.Authenticated) { if (token == null) { throw new ArgumentException("The request endpoint requires SSO authentication and a Token has not been provided."); } client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); } if (ETag != null) { client.DefaultRequestHeaders.Add("If-None-Match", $"\"{ETag}\""); ETag = null; } //Attach query string parameters if (parameters != null) { url += $"&{string.Join("&", parameters)}"; } //Serialize post body data HttpContent postBody = null; if (body != null) { postBody = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); } //Get response from client based on request type //This is also where body variables will be created and attached as necessary HttpResponseMessage response = null; switch (method) { case RequestMethod.Delete: response = await client.DeleteAsync(url).ConfigureAwait(false); break; case RequestMethod.Get: response = await client.GetAsync(url).ConfigureAwait(false); break; case RequestMethod.Post: response = await client.PostAsync(url, postBody).ConfigureAwait(false); break; case RequestMethod.Put: response = await client.PutAsync(url, postBody).ConfigureAwait(false); break; } //Output final object var obj = new EsiResponse <T>(response, path, version); return(obj); }