Our expectation is to upload a document on Google drive if uses is logged in to the system. If first time user system will open a popup for login credentials. Below code is working fine on my development environment (localhost) but not on QA server when I publish the code on QA server.
Just for info, we are using Google API for authorization.
Below is my code snippet:
Google.Apis.Drive.v3.DriveService service = null;
try
{
UserCredential credential;
string credPath = AppDomain.CurrentDomain.BaseDirectory;
credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = ConfigurationManager.AppSettings["client_id"],
ClientSecret = ConfigurationManager.AppSettings["client_secret"],
},
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
// Create Drive API service.
service = new Google.Apis.Drive.v3.DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
}
catch (Exception ex)
{
throw;
}
return service;
Below is an error message:
"Failed to launch browser with \"https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=123&redirect_uri=http%3A%2F%2Flocalhost%3A54597%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive\" for authorization.
Related
I have 2 ASP.NET Core 2.1 applications (Auth and API) using Identity Server 4.
On API application Startup I have the following:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(x =>
x.ApiName = "api";
x.Authority = "https://localhost:5005";
x.RequireHttpsMetadata = false;
});
On Auth application Startup I have the following configuration:
services
.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers());
Where Config class is the following:
public class Config {
public static List<ApiResource> GetApiResources() {
return new List<ApiResource> {
new ApiResource("api", "API Resource")
};
}
public static List<IdentityResource> GetIdentityResources() {
return new List<IdentityResource> {
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
public static List<Client> GetClients() {
return new List<Client> {
new Client {
ClientId = "app",
ClientName = "APP Client",
ClientSecrets = { new Secret("pass".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = {
"api"
}
}
}
public static List<TestUser> GetTestUsers() {
return new List<TestUser> {
new TestUser {
SubjectId = "1",
Username = "john",
Password = "john",
Claims = new List<Claim> { new Claim("name", "John") } },
};
}
}
With Postman I am able to access .well-known/openid-configuration and create an Access Token.
However, when I call the API I get the following error:
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
Exception occurred while processing message.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden by default.
Set the 'ShowPII' flag in IdentityModelEventSource.cs to true to reveal it.]'. ---> System.IO.IOException: IDX20804: Unable to retrieve document from: '[PII is hidden by default.
Set the 'ShowPII' flag in IdentityModelEventSource.cs to true to reveal it.]'. ---> System.Net.Http.HttpRequestException:
The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
I ran dotnet dev-certs https --trust; and the localhost certificate appears on Mac Keychain.
Important
On a Windows computer the code I posted works fine.
I am able to access .well-known/openid-configuration and the API endpoint.
What am I missing?
today i use the demo of identityserver4 Build a validation server, and i can use the asp.net core client with openid login the client.
but i could not login my asp.net mvc5 client with openid, The error of the prompt is : invalid_request,
here is my identityserver4 config code with getclient()
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
// OpenID Connect hybrid flow and client credentials client (MVC)
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = true,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
}
};
}
}
and the follow code is my asp.net mvc5 clent ConfigureAuth(),because the idenetiyServer4 define the ClientSecrets is "secret".Sha256(),so in this mvc client , i set the ClientSecret = GetSHA256HashFromString("secret"),i create prvate the method GetSHA256HashFromString() to convert the string to sha256.
here is my code:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookies",
Authority = "http://localhost:5000", //ID Server SSO Server
ClientId = "mvc",
ClientSecret = GetSHA256HashFromString("secret"),
ResponseType = "code id_token",
RedirectUri = "http://localhost:5002/signin-oidc", //URL of Client website
PostLogoutRedirectUri = "http://localhost:5002/signout-callback-oidc", //URL of Client website
Scope = "api1",
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
RequireHttpsMetadata = false,
});
and i press f5 to run the mvc client ,and press the button of login,the brower can jump to the localhost:5000,but it is give me a error:
Sorry, there was an error : invalid_request and the other error info are :
Request Id: 0HL9RHBTJIT3T:00000003**
thanks a lot.
The value of ClientSecret should be the actual secret value not the hashed one.
The secret is stored as hash when you use a persisted data storage to prevent an attacker to obtain your client's secrets in case if your storage is compromised.
In your case, The secret value is "secret". So the code will be
ClientSecret = "secret"
I am making a single sign on solution for multiple products and need to be able to log the user into their google account so that they can use other google services like drive and email etc. I am getting access tokens and storing them using the Google.Apis.Auth.OAuth2.Mvc and sample code but I am unsure how to use this token to log the user in. I don't need api access just need to ensure that after the user has gone through the flow the next time they visit my site they are logged into their google account. This is a .net mvc project.
public async Task<ActionResult> IndexAsync(CancellationToken cancellationToken)
{
var result = await new AuthorizationCodeMvcApp(this, flowData).AuthorizeAsync(cancellationToken);
if (result == null || result.Credential == null)
return new RedirectResult(result.RedirectUri);
return new RedirectResult(Request.UrlReferrer.AbsolutePath);
}
initiater = new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "30725746816-ev4dn6bt84cmj8ksemsrh894lcngh45q.apps.googleusercontent.com",
ClientSecret = "-Sm8vvVjlIsR8M4AxMR8-MZw",
},
Scopes = new[] { "openid profile email" },
DataStore = new GoogleIDataStore(_session, user),
};
currentUser = user;
flow = new GoogleAuthorizationCodeFlow(initiater);
MVC 5 app with Microsoft Owin v3 authenticating users via Windows Azure Active Directory. I have a login process that I don't fully understand. I expect to see a cookie on every request by I only see one on the landing page after sign-in. After navigating to another controller the cookie disappears yet the session appears to be authenticated correctly. Does anyone know how this is working? Here is my sign on logic...I don't see any cookie with the expiry time set in any browser. I see .AspNet.Cookies, __RequestVerificationToken and 2 cookies associated with a support utility. Removing any of these using Firebug has no effect on the user session and I remain logged in.
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/", IsPersistent = true, AllowRefresh = true, ExpiresUtc = DateTime.UtcNow.AddMinutes(20) },
OpenIdConnectAuthenticationDefaults.AuthenticationType
);
And here is the startup logic taken from an online example...
public void ConfigureAuth(IAppBuilder app)
{
//TODO: Use the Ioc container to get this but need to check if the kernel has been created before this runs
string applicationClientId = ConfigurationManager.AppSettings.Get(ConfigurationConstants.AppSettings.AzureApplicationClientId);
//fixed address for multitenant apps in the public cloud
string authority = "https://login.windows.net/common/";
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieDomain = "example.com" });
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = applicationClientId,
Authority = authority,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
// instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
// we inject our own multitenant validation logic
ValidateIssuer = false,
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = (context) =>
{
// This ensures that the address used for sign in and sign out is picked up dynamically from the request
// this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
// Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
context.ProtocolMessage.RedirectUri = appBaseUrl;
//This will need changing to the web site home page once it is live
context.ProtocolMessage.PostLogoutRedirectUri = "http://www.example.com";
return Task.FromResult(0);
},
// we use this notification for injecting our custom logic
SecurityTokenValidated = (context) =>
{
// retriever caller data from the incoming principal
string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
string tenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
//Todo - fetch the tenant info
//if ((db.Tenants.FirstOrDefault(a => ((a.IdentityProvider == issuer) && (a.ActiveDirectoryTenantId == tenantId))) == null))
// // the caller wasn't from a trusted issuer throw to block the authentication flow
// throw new SecurityTokenValidationException();
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.OwinContext.Response.Redirect("/Home/Error");
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
}
});
}
This initial login succeeds:
public static MobileServiceClient MOBILE = new MobileServiceClient("https://myapp.azure-mobile.net/",myApplicationKey);
MobileServiceAuthenticationProvider GOOGLEPROVIDER = MobileServiceAuthenticationProvider.Google;
private async Task Connect() {
var USER = await MOBILE.LoginAsync(this, GOOGLEPROVIDER);
var CACHE = new Dictionary<string, string> { { "token", USER.MobileServiceAuthenticationToken } };
var ACCOUNT = new Account(USER.UserId, CACHE);
var STORE = AccountStore.Create(this);
STORE.Save(ACCOUNT, "Google");
}
but then this attempt to reuse the token to reconnect without a login page fails:
public async Task Reconnect() {
var STORE = AccountStore.Create(this);
var token = STORE.FindAccountsForService("Google").ToArray()[0].Properties["token"];
// token seems ok
var jsonToken = new JObject();
jsonToken.Add("access_token", token);
var USER = await MOBILE.LoginAsync(MobileServiceAuthenticationProvider.Google, jsonToken); // BOOM!
}
... with the following message: "The POST Google login request must contain both code and id_token in the body of the request."
What I am getting wrong here?
The token you use in the code, viz.
var CACHE = new Dictionary { { "token",USER.MobileServiceAuthenticationToken } };
The MobileServiceAuthenticationToken above is a token specific to MobileServices and cannot be used in the LoginAsync method (LoginAsync method requires a Google OAuth token.)
Please see this Get User Info from Google Api Using Azure Mobile Services for Xamarin Android