/// <summary> /// /// </summary> /// <param name="session">Ramone session.</param> /// <param name="scope">Space separated list of strings identifying the required scopes (as defined by the authorization server).</param> /// <param name="extraRequestArgs">Optionally specify extra arguments in the POST data of the HTTP request.</param> /// <param name="useAccessToken">Store the returned access token in session and use that in future requests to the resource server.</param> /// <returns></returns> public static OAuth2AccessTokenResponse OAuth2_GetAccessTokenUsingClientCredentials( this ISession session, string scope = null, IDictionary <string, string> extraRequestArgs = null, bool useAccessToken = true) { OAuth2Settings settings = GetSettings(session); NameValueCollection tokenRequestArgs = new NameValueCollection(); tokenRequestArgs["grant_type"] = "client_credentials"; if (scope != null) { tokenRequestArgs["scope"] = scope; } if (extraRequestArgs != null) { foreach (var kv in extraRequestArgs) { tokenRequestArgs[kv.Key] = kv.Value; } } if (settings.ClientAuthenticationMethod == OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody) { tokenRequestArgs["client_id"] = settings.ClientID; tokenRequestArgs["client_secret"] = settings.ClientSecret; } return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
/// <summary> /// Request access token, passing the supplied args to the OAuth2 endpoint. /// </summary> /// <param name="session"></param> /// <param name="args"></param> /// <param name="useAccessToken">Store the returned access token in session and use that in future requests to the resource server.</param> /// <returns></returns> public static OAuth2AccessTokenResponse GetAndStoreAccessToken(ISession session, object args, bool useAccessToken) { OAuth2Settings settings = GetSettings(session); Request request = session.Bind(settings.TokenEndpoint) .AsFormUrlEncoded() .AcceptJson(); if (settings.ClientAuthenticationMethod == OAuth2Settings.DefaultClientAuthenticationMethods.BasicAuthenticationHeader) { request = request.BasicAuthentication(settings.ClientID, settings.ClientSecret); } using (var response = request.AcceptJson().Post <Hashtable>(args)) { OAuth2AccessTokenResponse accessToken = new OAuth2AccessTokenResponse { access_token = TryGet <string>(response.Body["access_token"]), token_type = TryGet <string>(response.Body["token_type"]), expires_in = TryGet <long?>(response.Body["expires_in"]), refresh_token = TryGet <string>(response.Body["refresh_token"]), AllParameters = response.Body }; if (useAccessToken) { OAuth2SessionState state = session.OAuth2_GetOrCreateState(); state.AccessToken = accessToken.access_token; state.TokenType = ParseAccessTokenType(accessToken.token_type); OAuth2_ActivateAuthorization(session, accessToken.access_token, state.TokenType); } return(accessToken); } }
/// <summary> /// Request an access token from authorization code acquired in earlier requests. /// </summary> /// <remarks>See http://tools.ietf.org/html/rfc6749#section-4.1.3</remarks> /// <param name="session">Ramone session.</param> /// <param name="authorizationCode"></param> /// <param name="extraRequestArgs">Optionally specify extra arguments in the POST data of the HTTP request.</param> /// <param name="useAccessToken">Request automatic use of the returned access token in following requests.</param> /// <returns></returns> public static OAuth2AccessTokenResponse OAuth2_GetAccessTokenFromAuthorizationCode( this ISession session, string authorizationCode, IDictionary <string, string> extraRequestArgs = null, bool useAccessToken = true) { OAuth2Settings settings = GetSettings(session); NameValueCollection tokenRequestArgs = new NameValueCollection(); tokenRequestArgs["grant_type"] = "authorization_code"; tokenRequestArgs["code"] = authorizationCode; tokenRequestArgs["redirect_uri"] = settings.RedirectUri.ToString(); if (extraRequestArgs != null) { foreach (var kv in extraRequestArgs) { tokenRequestArgs[kv.Key] = kv.Value; } } if (settings.ClientAuthenticationMethod == OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody) { tokenRequestArgs["client_id"] = settings.ClientID; tokenRequestArgs["client_secret"] = settings.ClientSecret; } return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
/// <summary> /// Get an access token using the flow "Client Credentials Grant" with JWT client credentials signed with a generic algorithm. /// </summary> /// <param name="session">Ramone session.</param> /// <param name="signingAlgorithm">An implementation of ISigningAlgorithm to do the actual signing.</param> /// <param name="args">Assertion arguments.</param> /// <param name="useAccessToken">Store the returned access token in session and use that in future requests to the resource server.</param> /// <returns></returns> public static OAuth2AccessTokenResponse OAuth2_GetAccessTokenFromJWT(this ISession session, Jose.JwsAlgorithm alg, object key, AssertionArgs args, bool useAccessToken = true) { OAuth2Settings settings = GetSettings(session); DateTime now = DateTime.UtcNow; DateTime issuedAtDate = now.Add(args.IssueTimeOffset); DateTime expiresDate = issuedAtDate.Add(args.ExpireTime); long issuedAt = issuedAtDate.ToUnixTime(); long expires = expiresDate.ToUnixTime(); var claims = new Dictionary <string, object>() { { "iss", args.Issuer }, { "scope", args.Scope }, { "aud", args.Audience }, { "sub", args.Subject }, { "exp", expires }, { "iat", issuedAt } }; claims = claims.Where(kv => kv.Value != null).ToDictionary(kv => kv.Key, kv => kv.Value); string token = Jose.JWT.Encode(claims, key, alg); NameValueCollection tokenRequestArgs = new NameValueCollection(); tokenRequestArgs["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; tokenRequestArgs["assertion"] = token; return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
/// <summary> /// Request an access token using the flow "Resource Owner Password Credentials Grant". /// </summary> /// <remarks>See http://tools.ietf.org/html/rfc6749#section-4.3</remarks> /// <param name="session">Ramone session.</param> /// <param name="ownerUserName"></param> /// <param name="ownerPassword"></param> /// <param name="scope">Space separated list of strings identifying the required scopes (as defined by the authorization server).</param> /// <param name="useAccessToken">Request automatic use of the returned access token in following requests.</param> /// <returns></returns> public static OAuth2AccessTokenResponse OAuth2_GetAccessTokenUsingOwnerUsernamePassword( this ISession session, string ownerUserName, string ownerPassword, string scope = null, bool useAccessToken = true) { OAuth2Settings settings = GetSettings(session); NameValueCollection tokenRequestArgs = new NameValueCollection(); tokenRequestArgs["grant_type"] = "password"; tokenRequestArgs["username"] = ownerUserName; if (ownerPassword != null) { tokenRequestArgs["password"] = ownerPassword; } if (scope != null) { tokenRequestArgs["scope"] = scope; } if (settings.ClientAuthenticationMethod == OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody) { tokenRequestArgs["client_id"] = settings.ClientID; tokenRequestArgs["client_secret"] = settings.ClientSecret; } return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
/// <summary> /// Configure OAuth2 and store configuration in session for later use. /// Must always be called before using any of the other OAuth2 methods. /// </summary> /// <param name="session">Ramone session.</param> /// <param name="settings"></param> /// <returns>The session passed in as argument.</returns> public static ISession OAuth2_Configure(this ISession session, OAuth2Settings settings) { Condition.Requires(settings, "settings").IsNotNull(); session.Items[OAuth2SettingsSessionKey] = settings; return(session); }
public static OAuth2AccessTokenResponse OAuth2_RefreshAccessToken(this ISession session, string refreshToken, string scope = null, bool useAccessToken = true) { OAuth2Settings settings = GetSettings(session); NameValueCollection tokenRequestArgs = new NameValueCollection(); tokenRequestArgs["grant_type"] = "refresh_token"; tokenRequestArgs["refresh_token"] = refreshToken; tokenRequestArgs["scope"] = scope; if (settings.ClientAuthenticationMethod == OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody) { tokenRequestArgs["client_id"] = settings.ClientID; tokenRequestArgs["client_secret"] = settings.ClientSecret; } return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
/// <summary> /// Get URL for user authorization via browser (user agent). This will initiate the "Authorization Code Grant" flow. /// </summary> /// <remarks>See http://tools.ietf.org/html/rfc6749#section-4.1.1</remarks> /// <param name="session">Ramone session.</param> /// <param name="scope">Space separated list of strings identifying the required scopes (as defined by the authorization server).</param> /// <returns>Authorization request URL.</returns> public static Uri OAuth2_GetAuthorizationRequestUrl(this ISession session, string scope = null) { OAuth2Settings settings = GetSettings(session); string authorizationRequestState = RandomStrings.GetRandomStringWithLettersAndDigitsOnly(20); OAuth2SessionState state = session.OAuth2_GetOrCreateState(); state.AuthorizationState = authorizationRequestState; var codeRequestArgs = new { response_type = "code", client_id = settings.ClientID, redirect_uri = settings.RedirectUri.ToString(), scope = scope, state = authorizationRequestState }; return(settings.AuthorizationEndpoint.AddQueryParameters(codeRequestArgs)); }
/// <summary> /// Get an access token using either the flow "JWTs as Authorization Grants" defined in RFC 7523 Section 2.1 or /// "Client Acting on Behalf of Itself" defined in RFC 7521 Section 6.2 with JWT client credentials signed with a generic algorithm. /// </summary> /// <param name="session">Ramone session.</param> /// <param name="alg">An implementation of ISigningAlgorithm to do the actual signing.<</param> /// <param name="key">The key used by the signing algorithm.</param> /// <param name="args">Assertion arguments.</param> /// <param name="flowType">Specify which client authentication flow to use.</param> /// <param name="extraHeaders">Optionally specify extra headers in the assertion.</param> /// <param name="extraClaims">Optionally specify extra claims in the assertion.</param> /// <param name="extraRequestArgs">Optionally specify extra arguments in the POST data of the HTTP request.</param> /// <param name="useAccessToken">Store the returned access token in session and use that in future requests to the resource server.</param> /// <returns></returns> public static OAuth2AccessTokenResponse OAuth2_GetAccessTokenFromJWT( this ISession session, Jose.JwsAlgorithm alg, object key, AssertionArgs args, ClientAuthenticationFlowType flowType, IDictionary <string, object> extraHeaders = null, IDictionary <string, object> extraClaims = null, IDictionary <string, string> extraRequestArgs = null, bool useAccessToken = true) { if (args == null) { throw new ArgumentNullException(nameof(args)); } if (flowType != ClientAuthenticationFlowType.Rfc7523Section21 && flowType != ClientAuthenticationFlowType.Rfc7521Section62) { throw new ArgumentOutOfRangeException(nameof(flowType)); } OAuth2Settings settings = GetSettings(session); DateTime now = DateTime.UtcNow; DateTime issuedAtDate = now.Add(args.IssueTimeOffset); DateTime expiresDate = issuedAtDate.Add(args.ExpireTime); long issuedAt = issuedAtDate.ToUnixTime(); long expires = expiresDate.ToUnixTime(); IEnumerable <KeyValuePair <string, object> > baseClaims = new Dictionary <string, object>() { { "iss", args.Issuer }, { "scope", args.Scope }, { "aud", args.Audience }, { "sub", args.Subject }, { "exp", expires }, { "iat", issuedAt } }; if (extraClaims != null) { baseClaims = baseClaims.Concat(extraClaims); } var claims = baseClaims.Where(kv => kv.Value != null).ToDictionary(kv => kv.Key, kv => kv.Value); string token = Jose.JWT.Encode(claims, key, alg, extraHeaders: extraHeaders); NameValueCollection tokenRequestArgs = new NameValueCollection(); if (flowType == ClientAuthenticationFlowType.Rfc7523Section21) { tokenRequestArgs["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; tokenRequestArgs["assertion"] = token; } else { tokenRequestArgs["scope"] = args.Scope; // This is nominally optional and redundant, but Microsoft wants it... tokenRequestArgs["grant_type"] = "client_credentials"; tokenRequestArgs["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; tokenRequestArgs["client_assertion"] = token; } if (extraRequestArgs != null) { foreach (var kv in extraRequestArgs) { tokenRequestArgs[kv.Key] = kv.Value; } } return(GetAndStoreAccessToken(session, tokenRequestArgs, useAccessToken)); }
static void Setup() { // Create new session with implicit service Session = RamoneConfiguration.NewSession(new Uri(GoogleAPIBaseUrl)); // Get Google API keys from file (don't want the secret parts hardcoded in public repository) GoogleKeys keys = new GoogleKeys(); if (SelectedAccessType != AccessType.JWT) keys = ReadKeys(); // Configure OAuth2 with the stuff it needs for it's magic OAuth2Settings settings = new OAuth2Settings { TokenEndpoint = new Uri(TokenEndpointUrl) }; if (SelectedAccessType == AccessType.PinCode) { settings.AuthorizationEndpoint = new Uri(AuthorizationEndpointUrl); settings.RedirectUri = new Uri("urn:ietf:wg:oauth:2.0:oob"); settings.ClientID = keys.ClientId; settings.ClientSecret = keys.ClientSecret; settings.ClientAuthenticationMethod = OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody; } else if (SelectedAccessType == AccessType.Redirect) { settings.AuthorizationEndpoint = new Uri(AuthorizationEndpointUrl); settings.RedirectUri = new Uri("http://localhost"); settings.ClientID = keys.ClientId; settings.ClientSecret = keys.ClientSecret; settings.ClientAuthenticationMethod = OAuth2Settings.DefaultClientAuthenticationMethods.RequestBody; } else { settings.ClientAuthenticationMethod = OAuth2Settings.DefaultClientAuthenticationMethods.Other; } Session.OAuth2_Configure(settings); }