feat: log in with tumblr
This commit is contained in:
		
							parent
							
								
									d30ebacc72
								
							
						
					
					
						commit
						3338243cea
					
				
					 10 changed files with 342 additions and 9 deletions
				
			
		|  | @ -53,14 +53,12 @@ public partial class RemoteAuthService | |||
|             throw new FoxnounsError("Invalid Discord OAuth response"); | ||||
|         } | ||||
| 
 | ||||
|         DiscordTokenResponse? token = await resp.Content.ReadFromJsonAsync<DiscordTokenResponse>( | ||||
|             ct | ||||
|         ); | ||||
|         OauthTokenResponse? token = await resp.Content.ReadFromJsonAsync<OauthTokenResponse>(ct); | ||||
|         if (token == null) | ||||
|             throw new FoxnounsError("Discord token response was null"); | ||||
| 
 | ||||
|         var req = new HttpRequestMessage(HttpMethod.Get, _discordUserUri); | ||||
|         req.Headers.Add("Authorization", $"{token.token_type} {token.access_token}"); | ||||
|         req.Headers.Add("Authorization", $"{token.TokenType} {token.AccessToken}"); | ||||
| 
 | ||||
|         HttpResponseMessage resp2 = await _httpClient.SendAsync(req, ct); | ||||
|         resp2.EnsureSuccessStatusCode(); | ||||
|  |  | |||
							
								
								
									
										111
									
								
								Foxnouns.Backend/Services/Auth/RemoteAuthService.Tumblr.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								Foxnouns.Backend/Services/Auth/RemoteAuthService.Tumblr.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| // Copyright (C) 2023-present sam/u1f320 (vulpine.solutions) | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU Affero General Public License as published | ||||
| // by the Free Software Foundation, either version 3 of the License, or | ||||
| // (at your option) any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| // GNU Affero General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU Affero General Public License | ||||
| // along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| using System.Text.Json.Serialization; | ||||
| 
 | ||||
| namespace Foxnouns.Backend.Services.Auth; | ||||
| 
 | ||||
| public partial class RemoteAuthService | ||||
| { | ||||
|     private readonly Uri _tumblrTokenUri = new("https://api.tumblr.com/v2/oauth2/token"); | ||||
|     private readonly Uri _tumblrUserUri = new("https://api.tumblr.com/v2/user/info"); | ||||
| 
 | ||||
|     public async Task<RemoteUser> RequestTumblrTokenAsync( | ||||
|         string code, | ||||
|         CancellationToken ct = default | ||||
|     ) | ||||
|     { | ||||
|         var redirectUri = $"{config.BaseUrl}/auth/callback/tumblr"; | ||||
|         HttpResponseMessage resp = await _httpClient.PostAsync( | ||||
|             _tumblrTokenUri, | ||||
|             new FormUrlEncodedContent( | ||||
|                 new Dictionary<string, string> | ||||
|                 { | ||||
|                     { "client_id", config.TumblrAuth.ClientId! }, | ||||
|                     { "client_secret", config.TumblrAuth.ClientSecret! }, | ||||
|                     { "grant_type", "authorization_code" }, | ||||
|                     { "code", code }, | ||||
|                     { "scope", "basic" }, | ||||
|                     { "redirect_uri", redirectUri }, | ||||
|                 } | ||||
|             ), | ||||
|             ct | ||||
|         ); | ||||
|         if (!resp.IsSuccessStatusCode) | ||||
|         { | ||||
|             string respBody = await resp.Content.ReadAsStringAsync(ct); | ||||
|             _logger.Error( | ||||
|                 "Received error status {StatusCode} when exchanging OAuth token: {ErrorBody}", | ||||
|                 (int)resp.StatusCode, | ||||
|                 respBody | ||||
|             ); | ||||
|             throw new FoxnounsError("Invalid Tumblr OAuth response"); | ||||
|         } | ||||
| 
 | ||||
|         OauthTokenResponse? token = await resp.Content.ReadFromJsonAsync<OauthTokenResponse>(ct); | ||||
|         if (token == null) | ||||
|             throw new FoxnounsError("Tumblr token response was null"); | ||||
| 
 | ||||
|         var req = new HttpRequestMessage(HttpMethod.Get, _tumblrUserUri); | ||||
|         req.Headers.Add("Authorization", $"Bearer {token.AccessToken}"); | ||||
| 
 | ||||
|         HttpResponseMessage resp2 = await _httpClient.SendAsync(req, ct); | ||||
|         if (!resp2.IsSuccessStatusCode) | ||||
|         { | ||||
|             string respBody = await resp2.Content.ReadAsStringAsync(ct); | ||||
|             _logger.Error( | ||||
|                 "Received error status {StatusCode} when exchanging OAuth token: {ErrorBody}", | ||||
|                 (int)resp2.StatusCode, | ||||
|                 respBody | ||||
|             ); | ||||
|             throw new FoxnounsError("Invalid Tumblr user response"); | ||||
|         } | ||||
| 
 | ||||
|         TumblrData? data = await resp2.Content.ReadFromJsonAsync<TumblrData>(ct); | ||||
|         if (data == null) | ||||
|             throw new FoxnounsError("Tumblr user response was null"); | ||||
| 
 | ||||
|         TumblrBlog? blog = data.Response.User.Blogs.FirstOrDefault(b => b.Primary); | ||||
|         if (blog == null) | ||||
|             throw new FoxnounsError("Tumblr user doesn't have a primary blog"); | ||||
| 
 | ||||
|         return new RemoteUser(blog.Uuid, blog.Name); | ||||
|     } | ||||
| 
 | ||||
|     private record OauthTokenResponse( | ||||
|         [property: JsonPropertyName("access_token")] string AccessToken, | ||||
|         [property: JsonPropertyName("token_type")] string TokenType | ||||
|     ); | ||||
| 
 | ||||
|     // tumblr why | ||||
|     private record TumblrData( | ||||
|         [property: JsonPropertyName("meta")] TumblrMeta Meta, | ||||
|         [property: JsonPropertyName("response")] TumblrResponse Response | ||||
|     ); | ||||
| 
 | ||||
|     private record TumblrMeta( | ||||
|         [property: JsonPropertyName("status")] int Status, | ||||
|         [property: JsonPropertyName("msg")] string Message | ||||
|     ); | ||||
| 
 | ||||
|     private record TumblrResponse([property: JsonPropertyName("user")] TumblrUser User); | ||||
| 
 | ||||
|     private record TumblrUser([property: JsonPropertyName("blogs")] TumblrBlog[] Blogs); | ||||
| 
 | ||||
|     private record TumblrBlog( | ||||
|         [property: JsonPropertyName("name")] string Name, | ||||
|         [property: JsonPropertyName("primary")] bool Primary, | ||||
|         [property: JsonPropertyName("uuid")] string Uuid | ||||
|     ); | ||||
| } | ||||
|  | @ -19,7 +19,6 @@ using Foxnouns.Backend.Database.Models; | |||
| using Foxnouns.Backend.Extensions; | ||||
| using Foxnouns.Backend.Utils; | ||||
| using Humanizer; | ||||
| using JetBrains.Annotations; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Foxnouns.Backend.Services.Auth; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue