Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Auth Query Params (2) #666

Merged
merged 7 commits into from Jan 30, 2016
Expand Up @@ -100,6 +100,7 @@
<Compile Include="OAuth2\ComputeCredentialTests.cs" />
<Compile Include="OAuth2\Flows\AuthorizationCodeFlowTests.cs" />
<Compile Include="OAuth2\BearerTokenTests.cs" />
<Compile Include="OAuth2\Flows\GoogleAuthorizationCodeFlowTests.cs" />
<Compile Include="OAuth2\Requests\AuthorizationCodeRequestUrlTests.cs" />
<Compile Include="OAuth2\Requests\AuthorizationCodeTokenRequestTests.cs" />
<Compile Include="OAuth2\Requests\GoogleAuthorizationCodeRequestUrlTest.cs" />
Expand Down
@@ -0,0 +1,85 @@
/*
Copyright 2016 Google Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Moq;
using NUnit.Framework;

using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Http;
using Google.Apis.Util.Store;

namespace Google.Apis.Auth.OAuth2.Flows
{
/// <summary>Tests for <see cref="Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow"/>.</summary>
public class GoogleAuthorizationCodeFlowTests
{
GoogleAuthorizationCodeFlow.Initializer initializer { get; set; }
List<KeyValuePair<string, string>> userDefinedParams { get; set; }

[SetUp]
public void GoogleAuthorizationCodeFlowTestSetup()
{
string revokeTokenUrl = "Revoke Token Url";
bool? includeGrantedScopes = true;
userDefinedParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string,string>("customParam1","customVal1"),
new KeyValuePair<string,string>("customParam2","customVal2")
};

initializer = new GoogleAuthorizationCodeFlow.Initializer()
{
RevokeTokenUrl = revokeTokenUrl,
IncludeGrantedScopes = includeGrantedScopes,
UserDefinedQueryParams = userDefinedParams,
ClientSecrets = new ClientSecrets()
};
}

[Test]
public void ConstructorTest()
{
var flow = new GoogleAuthorizationCodeFlow(initializer);

Assert.That(flow.RevokeTokenUrl, Is.EqualTo(initializer.RevokeTokenUrl));
Assert.That(flow.IncludeGrantedScopes, Is.EqualTo(initializer.IncludeGrantedScopes));
Assert.That(flow.UserDefinedQueryParams, Is.EqualTo(initializer.UserDefinedQueryParams));
}

[Test]
public void CreateAuthorizationCodeRequestTest()
{
var flow = new GoogleAuthorizationCodeFlow(initializer);

var request = flow.CreateAuthorizationCodeRequest("TestRedirectUri") as GoogleAuthorizationCodeRequestUrl;

Assert.AreEqual(request.AccessType, "offline");
Assert.AreEqual(request.IncludeGrantedScopes, "true");
Assert.AreEqual(request.UserDefinedQueryParams, userDefinedParams);
Assert.AreEqual(request.RedirectUri, "TestRedirectUri");
}

//TODO(squid808): Add tests for RevokeToken.
}
}
Expand Up @@ -15,6 +15,7 @@
*/

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -40,12 +41,21 @@ public class GoogleAuthorizationCodeFlow : AuthorizationCodeFlow
/// <summary>Gets or sets the include granted scopes indicator.</summary>
public bool? IncludeGrantedScopes { get { return includeGrantedScopes; } }

private readonly IEnumerable<KeyValuePair<string, string>> userDefinedQueryParams;

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


/// <summary>Gets the user defined query parameters.</summary>
public IEnumerable<KeyValuePair<string, string>> UserDefinedQueryParams
{
get { return userDefinedQueryParams; }
}

/// <summary>Constructs a new Google authorization code flow.</summary>
public GoogleAuthorizationCodeFlow(Initializer initializer)
: base(initializer)
{
revokeTokenUrl = initializer.RevokeTokenUrl;
includeGrantedScopes = initializer.IncludeGrantedScopes;
userDefinedQueryParams = initializer.UserDefinedQueryParams;
}

public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
Expand All @@ -56,7 +66,8 @@ public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(strin
Scope = string.Join(" ", Scopes),
RedirectUri = redirectUri,
IncludeGrantedScopes = IncludeGrantedScopes.HasValue
? IncludeGrantedScopes.Value.ToString().ToLower() : null
? IncludeGrantedScopes.Value.ToString().ToLower() : null,
UserDefinedQueryParams = UserDefinedQueryParams
};
}

Expand Down Expand Up @@ -91,9 +102,14 @@ public new class Initializer : AuthorizationCodeFlow.Initializer
/// <summary>Gets or sets the token revocation URL.</summary>
public string RevokeTokenUrl { get; set; }

/// <summary>Gets or sets the optional indicator for including granted scopes for incremental authorization.</summary>
/// <summary>
/// Gets or sets the optional indicator for including granted scopes for incremental authorization.
/// </summary>
public bool? IncludeGrantedScopes { get; set; }

/// <summary>Gets or sets the optional user defined query parameters.</summary>
public IEnumerable<KeyValuePair<string, string>> UserDefinedQueryParams { get; set; }

/// <summary>
/// Constructs a new initializer. Sets Authorization server URL to
/// <see cref="Google.Apis.Auth.OAuth2.GoogleAuthConsts.AuthorizationUrl"/>, and Token server URL to
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/

using System;
using System.Collections.Generic;

namespace Google.Apis.Auth.OAuth2.Requests
{
Expand Down Expand Up @@ -59,6 +60,18 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
Google.Apis.Util.RequestParameterType.Query)]
public string IncludeGrantedScopes { get; set; }

/// <summary>
/// Gets or sets a collection of user defined query parameters to facilitate any not explicitly supported
/// by the library which will be included in the resultant authentication URL.
/// </summary>
/// <remarks>
/// The name of this parameter is used only for the constructor and will not end up in the resultant query
/// string.
/// </remarks>
[Google.Apis.Util.RequestParameterAttribute("user_defined_query_params",
Google.Apis.Util.RequestParameterType.UserDefinedQueries)]
public IEnumerable<KeyValuePair<string, string>> UserDefinedQueryParams { get; set; }

/// <summary>
/// Constructs a new authorization code request with the given authorization server URL. This constructor sets
/// the <see cref="AccessType"/> to <c>offline</c>.
Expand Down
Expand Up @@ -20,6 +20,7 @@
using System.Linq;
using System.Reflection;

using Google.Apis.Logging;
using Google.Apis.Util;

namespace Google.Apis.Requests.Parameters
Expand All @@ -29,6 +30,8 @@ namespace Google.Apis.Requests.Parameters
/// </summary>
public static class ParameterUtils
{
private static readonly ILogger Logger = ApplicationContext.Logger.ForType(typeof(ParameterUtils));

/// <summary>
/// Creates a <see cref="System.Net.Http.FormUrlEncodedContent"/> with all the specified parameters in
/// the input request. It uses reflection to iterate over all properties with
Expand Down Expand Up @@ -111,7 +114,7 @@ private static void IterateParameters(object request, Action<RequestParameterTyp
continue;
}

// Get the name of this parameter from the attribute, if it doesn't exist take a lower-case variant of
// Get the name of this parameter from the attribute, if it doesn't exist take a lower-case variant of
// property name.
string name = attribute.Name ?? property.Name.ToLower();

Expand All @@ -121,7 +124,25 @@ private static void IterateParameters(object request, Action<RequestParameterTyp
// Call action with the type name and value.
if (propertyType.IsValueType || value != null)
{
action(attribute.Type, name, value);
if (attribute.Type == RequestParameterType.UserDefinedQueries)
{
if (typeof(IEnumerable<KeyValuePair<string, string>>).IsAssignableFrom(value.GetType()))

This comment was marked as spam.

{
foreach (var pair in (IEnumerable<KeyValuePair<string, string>>)value)
{
action(RequestParameterType.Query, pair.Key, pair.Value);
}
}
else
{
Logger.Warning("Parameter marked with RequestParameterType.UserDefinedQueries attribute " +
"was not of type IEnumerable<KeyValuePair<string, string>> and will be skipped.");
}
}
else
{
action(attribute.Type, name, value);
}
}
}
}
Expand Down
Expand Up @@ -56,21 +56,27 @@ public RequestParameterAttribute(string name)
/// string value into the path, replacing {name}. If the parameter is a query parameter, this parameter will be
/// added to the query string, in the format "name=value".
/// </param>
/// <param name="type">The type of the parameter, either Path or Query.</param>
/// <param name="type">The type of the parameter, either Path, Query or UserDefinedQueries.</param>
public RequestParameterAttribute(string name, RequestParameterType type)
{
this.name = name;
this.type = type;
}
}

/// <summary>Describe the type of this parameter (Path or Query).</summary>
/// <summary>Describe the type of this parameter (Path, Query or UserDefinedQueries).</summary>
public enum RequestParameterType
{
/// <summary>A path parameter which is inserted into the path portion of the request URI.</summary>
Path,

/// <summary>A query parameter which is inserted into the query portion of the request URI.</summary>
Query
Query,

/// <summary>
/// A group of user-defined parameters that will be added in to the query portion of the request URI. If this
/// type is being used, the name of the RequestParameterAttirbute is meaningless.
/// </summary>
UserDefinedQueries
}
}
@@ -0,0 +1,83 @@
/*
Copyright 2016 Google Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System.Collections.Generic;

using NUnit.Framework;

using Google.Apis.Util;
using Google.Apis.Requests;
using Google.Apis.Requests.Parameters;

namespace Google.Apis.Tests.Apis.Requests
{
/// <summary>Tests for <see cref="Google.Apis.Requests.Parameters.ParameterUtils"/>.</summary>
[TestFixture]
public class ParameterUtilsTest
{
private class TestRequestUrl
{
[Google.Apis.Util.RequestParameterAttribute("first_query_param",
Google.Apis.Util.RequestParameterType.Query)]
public string FirstParam { get; set; }

[Google.Apis.Util.RequestParameterAttribute("second_query_param",
Google.Apis.Util.RequestParameterType.Query)]
public string SecondParam { get; set; }

[Google.Apis.Util.RequestParameterAttribute("query_param_attribute_name",
Google.Apis.Util.RequestParameterType.UserDefinedQueries)]
public List<KeyValuePair<string, string>> ParamsCollection { get; set; }

public System.Uri Build()
{
var builder = new RequestBuilder()
{
BaseUri = new System.Uri("//revokeTokenUrl")
};
ParameterUtils.InitParameters(builder, this);
return builder.BuildUri();
}
}

[Test]
public void IterateParametersTest()

This comment was marked as spam.

{
var request = new TestRequestUrl()
{
FirstParam = "firstOne",
SecondParam = "secondOne",
ParamsCollection = new List<KeyValuePair<string, string>>{
new KeyValuePair<string,string>("customParam1","customVal1"),
new KeyValuePair<string,string>("customParam2","customVal2")
}
};

var result = request.Build().AbsoluteUri;

//Parametera were given a name and a value, so both appear in the URI.
Assert.That(result, Contains.Substring("first_query_param=firstOne"));
Assert.That(result, Contains.Substring("second_query_param=secondOne"));

This comment was marked as spam.


//Custom parameters are key value pairs representing parameter names and values respectively.
Assert.That(result, Contains.Substring("customParam1=customVal1"));
Assert.That(result, Contains.Substring("customParam2=customVal2"));

This comment was marked as spam.

This comment was marked as spam.


//The parameter name for the custom parameters does not carry through to the resulting URI.
Assert.IsFalse(result.Contains("query_param_attribute_name"));

This comment was marked as spam.

}
}
}
1 change: 1 addition & 0 deletions Src/Support/GoogleApis.Tests/GoogleApis.Tests.csproj
Expand Up @@ -138,6 +138,7 @@
<Compile Include="Apis\Requests\BatchRequestTest.cs" />
<Compile Include="Apis\Requests\PageStreamerTest.cs" />
<Compile Include="Apis\Requests\Parameters\ParameterCollectionTest.cs" />
<Compile Include="Apis\Requests\Parameters\ParameterUtilsTest.cs" />
<Compile Include="Apis\Requests\Parameters\ParameterValidatorTest.cs" />
<Compile Include="Apis\Requests\RequestBuilderTest.cs" />
<Compile Include="Apis\Services\BaseClientServiceTest.cs" />
Expand Down