Add authmethod config value for oidc providers (#453)

This commit is contained in:
Zoe Roux 2024-04-30 00:22:25 +02:00 committed by GitHub
parent 5f20d9102f
commit e1f1106c8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 6 deletions

View File

@ -55,6 +55,10 @@ OIDC_SERVICE_AUTHORIZATION=https://url-of-the-authorization-endpoint-of-the-oidc
OIDC_SERVICE_TOKEN=https://url-of-the-token-endpoint-of-the-oidc-service.com/token
OIDC_SERVICE_PROFILE=https://url-of-the-profile-endpoint-of-the-oidc-service.com/userinfo
OIDC_SERVICE_SCOPE="the list of scopes space separeted like email identity"
# Token authentication method as seen in https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
# Supported values: ClientSecretBasic (default) or ClientSecretPost
# If in doupt, leave this empty.
OIDC_SERVICE_AUTHMETHOD=ClientSecretBasic
# on the previous list, service is the internal name of your service, you can add as many as you want.

View File

@ -16,6 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -100,6 +101,20 @@ public static class AuthenticationModule
case "logo":
acc[provider].LogoUrl = val.Value;
break;
case "clientauthmethod":
case "authmethod":
case "auth":
case "method":
if (!Enum.TryParse(val.Value, out AuthMethod method))
{
Log.Error(
"Invalid AuthMethod value: {AuthMethod}. Ignoring.",
val.Value
);
break;
}
acc[provider].ClientAuthMethod = method;
break;
default:
Log.Error("Invalid oidc config value: {Key}", key);
return acc;

View File

@ -43,19 +43,27 @@ public class OidcController(
HttpClient client = clientFactory.CreateClient();
string auth = Convert.ToBase64String(
Encoding.UTF8.GetBytes($"{prov.ClientId}:{prov.Secret}")
);
client.DefaultRequestHeaders.Add("Authorization", $"Basic {auth}");
Dictionary<string, string> data =
new()
{
["code"] = code,
["client_id"] = prov.ClientId,
["client_secret"] = prov.Secret,
["redirect_uri"] = $"{options.PublicUrl.TrimEnd('/')}/api/auth/logged/{provider}",
["grant_type"] = "authorization_code",
};
if (prov.ClientAuthMethod == AuthMethod.ClientSecretBasic)
{
string auth = Convert.ToBase64String(
Encoding.UTF8.GetBytes($"{prov.ClientId}:{prov.Secret}")
);
client.DefaultRequestHeaders.Add("Authorization", $"Basic {auth}");
}
else if (prov.ClientAuthMethod == AuthMethod.ClientSecretPost)
{
data["client_id"] = prov.ClientId;
data["client_secret"] = prov.Secret;
}
HttpResponseMessage resp = prov.TokenUseJsonBody
? await client.PostAsJsonAsync(prov.TokenUrl, data)
: await client.PostAsync(prov.TokenUrl, new FormUrlEncodedContent(data));

View File

@ -67,6 +67,13 @@ public class PermissionOption
public Dictionary<string, OidcProvider> OIDC { get; set; }
}
public enum AuthMethod
{
ClientSecretBasic,
ClientSecretPost,
None,
}
public class OidcProvider
{
public string DisplayName { get; set; }
@ -79,6 +86,11 @@ public class OidcProvider
/// </summary>
public bool TokenUseJsonBody { get; set; }
/// <summary>
/// The OIDC spec allows multiples ways of authorizing the client.
/// </summary>
public AuthMethod ClientAuthMethod { get; set; } = AuthMethod.ClientSecretBasic;
public string ProfileUrl { get; set; }
public string? Scope { get; set; }
public string ClientId { get; set; }
@ -108,6 +120,7 @@ public class OidcProvider
ClientId = KnownProviders[provider].ClientId;
Secret = KnownProviders[provider].Secret;
TokenUseJsonBody = KnownProviders[provider].TokenUseJsonBody;
ClientAuthMethod = KnownProviders[provider].ClientAuthMethod;
GetProfileUrl = KnownProviders[provider].GetProfileUrl;
GetExtraHeaders = KnownProviders[provider].GetExtraHeaders;
}
@ -144,6 +157,7 @@ public class OidcProvider
// does not seems to have scopes
Scope = null,
TokenUseJsonBody = true,
ClientAuthMethod = AuthMethod.ClientSecretPost,
GetProfileUrl = (profile) => $"https://simkl.com/{profile.Sub}/dashboard/",
GetExtraHeaders = (OidcProvider self) =>
new() { ["simkl-api-key"] = self.ClientId },