Search code examples
asp.net-mvcgoogle-apigoogle-oauthgoogle-api-dotnet-client

Limit user authorization to my Google domain


It should be possible to limit Google API OAuth2 requests to a specific google domain. It used to be possible by hacking on the end &hd=mydomain.com to the request. Using the new MVC auth stuff it seems no longer possible. Any ideas how?

 public class AppFlowMetadata : FlowMetadata
    {
        private static readonly IAuthorizationCodeFlow flow =
            new AppGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = new ClientSecrets
                {
                    ClientId = "***.apps.googleusercontent.com",
                    ClientSecret = "******"
                },
                Scopes = new[] { DriveService.Scope.Drive },
                DataStore = new FileDataStore(HttpContext.Current.Server.MapPath("~/App_Data"), true) ,
            });  

        public override string GetUserId(Controller controller)
        {
            // In this sample we use the session to store the user identifiers.
            // That's not the best practice, because you should have a logic to identify
            // a user. You might want to use "OpenID Connect".
            // You can read more about the protocol in the following link:
            // https://developers.google.com/accounts/docs/OAuth2Login.
            var user = controller.Session["user"];
            if (user == null)
            {
                user = Guid.NewGuid();
                controller.Session["user"] = user;
            }
            return user.ToString();

        }

        public override IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }

public class AppGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
    {
        public AppGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }

        public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(String redirectUri)
        {

            var authorizeUri = new Uri(AuthorizationServerUrl).AddQuery("hd", "ourgoogledomain.com"); //is not in the request
            var authUrl = new GoogleAuthorizationCodeRequestUrl(authorizeUri)
            {
                ClientId = ClientSecrets.ClientId,
                Scope = string.Join(" ", Scopes),
                RedirectUri = redirectUri,
                //AccessType = "offline",
               // ApprovalPrompt = "force"
            };
            return authUrl;
        }
    }

Solution

  • Having downloaded the source, I was able to see it is easy to subclass the request object, and add custom parameters:

        public class GoogleDomainAuthorizationCodeRequestUrl : GoogleAuthorizationCodeRequestUrl
        {
            /// <summary>
            /// Gets or sets the hosted domain. 
            /// When you want to limit authorizing users from a specific domain 
            /// </summary>
            [Google.Apis.Util.RequestParameterAttribute("hd", Google.Apis.Util.RequestParameterType.Query)]
            public string Hd { get; set; }
    
            public GoogleDomainAuthorizationCodeRequestUrl(Uri authorizationServerUrl) : base(authorizationServerUrl)
            {
            }
        }
    
        public class AppGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
        {
            public AppGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
    
            public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(String redirectUri)
            {
                var authUrl = new GoogleDomainAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
                {
                    Hd = "mydomain.com",
                    ClientId = ClientSecrets.ClientId,
                    Scope = string.Join(" ", Scopes),
                    RedirectUri = redirectUri
                };
    
                return authUrl;
            }
        }