How to incoporate facebook login MVC 5 identity 2? - asp.net-mvc

In an account controller there is ExternalLogin action.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
I have appId and appSecrete set in StartUp. I'm running my application in local machine(localhost:port). I have custom facebook button(normal button).
I do not understand how I can call the external login from the button since the action above requires provider and return url. There is already ExternalLogin callback action as well.
When setting facebook application, I seem not to understand this part: Valid OAuth redirect URIs.
Please somebody help. The articles I read confuse me in this regard.
Edit: I can now connect to facebook, the only problem is I get an error:
URL Blocked: This redirect failed because the redirect URI is not
whitelisted in the app’s Client OAuth Settings. Make sure Client and
Web OAuth Login are on and add all your app domains as Valid OAuth
Redirect URIs.
I believe it is caused by Valid OAuth redirect URIs which is not set correctly.

Go to you facebook app development website. Open your page. Go to Facebook Login option under it go to setting option and change your Valid OAuth redirect URL. you have to give your website valid path in that section.
For local host you can try like this -
http://localhost:8080/fb_login_local/

Related

How to log out from application but not from Azure AD?

In my Asp.Net MVC application, I have recently integrated Azure AD authentication. The login is working fine, but I am not able to get the logout right. I would like to log the users out from my application only, and not "single sign out". Everything I have read is about single sign out. Here is what I have tried:
Abandon the session and redirect to login page. An error related to missing claims is thrown on the login page on Html.AntiForgeryToken() statement
Session.Abandon();
return RedirectToAction("Index", "Login");
This has the same error as #1
FederatedAuthentication.SessionAuthenticationModule.SignOut();
FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
return RedirectToAction("Index", "Login");
This takes user to single sign out
HttpContext.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
Here are a few of workarounds as suggested by #Jan Hajek here
Make sure that Azure AD is listed as a Connected Service in your .NET application.
This will prevent a single logout.
We can create single sign out endpoint in controller as below example
return SignOut(
new AuthenticationProperties
{
RedirectUri = callbackUrl,
},
CookieAuthenticationDefaults.AuthenticationScheme
);
NOTE: - When we hit the logout, it clears the cookies which is correct, because the user session (in case of Razor Pages and MVC) is stored in Cookies .
Also we can set redirect logout url (e.g- "<your-doman>/.auth/logout") to the home page of the application itself where it ask for log in again .
For more information please refer the below links
MS BLOG: Expanding App Service Authentication/Authorization
SO THREAD
MS DOC: Customize sign-in and sign-out in Azure App Service authentication

What is the point of PostLogoutRedirectUri in Open Id/OAuth2.0 logout?

I've been using Identity Server 4.0 as my OpenId Connect provider. I can setup clients in Identity Server with Redirect Uris and Post Logout Redirect Uris. I've also been using the angular-auth-oidc-client to login/logout via the Identity server.
When logging in, my client library (angular-auth-oidc-client) does pass in the correct Uri specified in the config when calling the authorize endpoint. When I try to login with an incorrect Redirect Uri, Identity Server checks and validates that the Uri provided by the client is one of the accepted one for that client, and shows an error if it isnt (as expected).
When it comes to logout, none of it seems to be built in. My client library does not send the PostLogoutRedirectUri when calling the logout endpoint. Identity Server's sample code for logout does not except any URIs to be passed in. It's sample code simply gets the Post Logout Redirect Uri value from the database and creates a link on the logged out page. Not only does the sample code not allow the user to specify the Redirect Uri for logout, but it doesn't do any checks or even do a redirect (granted its only sample code and I can change it). I would expect my client library to pass the Uri along and Identity Server to redirect to the Uri after successful logout as long as its one of the "approved" Uris for the client.
My question is: What even is the point of PostLogoutRedirectUri? Neither Identity Server nor the OIDC client library I'm using do anything useful with it. There doesn't even seem to be an agreed upon convention for the name of the query string parameters to use to pass this Uri to Identity Server. And yet, both the Identity Server and the angular client library seem to have some support for it. So what's the point of this thing? Is it something that will be added or fleshed out later? Did I miss some documentation describing what its for and how to use it?
It's a draft standard and support differs between libraries and vendors, but here is a summary:
A client uses the post logout redirect URI to log out in a controlled way, typically redirecting to an application page that gives the user a link to sign in again
A client could potentially have more than one post_logout_redirect_uri and decide which to use based on runtime conditions
The post_logout_redirect_uri sent is meant to only be honoured if it is accompanied by an id_token_hint - and if it matches a configured value against the OAuth client. I believe OIDC will send the current id token but it is worth checking that this is happening in your browser tools.
If a post_logout_redirect_uri is not sent then the Authorization Server may use the default one configured
See the official IETF docs on how this is meant to work.
In my own application, I set it to the /Signout-callback-oidc URL of the client, like
PostLogoutRedirectUris = { "https://localhost:5001/signout-callback-oidc" },
The /signout-callback-oidc path is defined as in the source code here:
/// <summary>
/// The request path within the application's base path where the user agent will be returned after sign out from the identity provider.
/// See post_logout_redirect_uri from http://openid.net/specs/openid-connect-session-1_0.html#RedirectionAfterLogout.
/// </summary>
public PathString SignedOutCallbackPath { get; set; }
I hope this can give some clarification.
There are two sessions, one in the UI, and another on the server. It might need to call a URL on the backend to remove the user session on the server, otherwise the server won't know you are logged out on the UI.

Attempting to connect to a IdentityServer4 login page fails

I have an existing website that I want to do a proof of concept with OAuth2 / OIDC. To this end I've configured a locally running IdentityServer4 MVC app as my demo OIDC server following the IdentityServer4 quick setup guidelines. This works fine and navigating to:
http://localhost:5000/.well-known/openid-configuration
Lets me see the discovery document.
I have created a fake login page on this OIDC app which consists of just a login button with no user credentials required.
There's no actual user database and I'm just hard coding some user details to return when the 'authentication' occurs.
In my pre-existing site I've added the OWIN middle wear and am configuring OIDC using the OpenIdConnectAuthenticationOptions. The clientId, scopes, secret etc all match as required and the authority is set to point to my locally running demo OIDC app (http://localhost:5000). The redirect url is set to return to my pre-existing site once authentication is complete.
This all appears to be fine but here's what I want to achieve and can't get working. On my pre-existing site when I navigate to any page that requires authentication I want the user to be redirected to the login page I created on OIDC app. They click the login button (no user details required) and are authenticated and redirected back to the original page.
Currently when I navigate to a protected page I am successfully redirected to the OIDC app but I am redirected to an error page and I don't know why. The error page gives me no detail, it's actually hard coded in the app.
When I look at the discovery document I see that the setting for the 'authorization_endpoint' is set to:
http://localhost:5000/connect/authorize
So I thought maybe I needed to either change that to point to Home/Login which is where I've created the dummy login form, or else I needed to actually create that connect/authorize endpoint and put my form there. Creating the end point makes no difference, it never gets hit and instead I just get the error page on my OIDC app. Changing it to home/login also appears to be ignored.
I am away from my main PC at the moment hence the lack of code snippets but essentially the set up is as per the IdentityServer4 quick setup guide and the OIDC app does appear to be working.
The issue is getting my pre-existing site to properly redirect to the login page.
I've been stuck on this for quite a while now and would like to even get to the stage of seeing the dummy login page. Any pointers are appreciated and again apologies for the lack of sample code.
UPDATE
I've got the login form appearing by setting the openidconfiguration like so:
Configuration = new OpenIdConnectConfiguration()
{
AuthorizationEndPoint = "http://localhost:5000/home/login"
}
However, this isn't logging me in when I click login. On that login action I'm doing this:
await HttpContext.SignInAsync("subjectId","username", authenticationProps);
And then redirecting back to my existing site. However it's not authenticating me and the redirect ends up being redirected back again to the login page.
UPDATE 2
I think the redirect URI should possibly be doing something more. Currently I do the following:
Try and access a restricted page -> Redirected to OIDC server -> Click Login (this sets the subject and user successfully) -> Am redirected to redirect URI which immediately bounces me back to the OIDC server.
So maybe the redirect URI is supposed to confirm login or otherwise do something?
So in the open id connect protocol, the authorize endpoint is used to validate the client information passed as query parameters (client_id, scopes, redirect_uri, etc). In your authentication server, none of that is being checked if all the endpoint does is return a form. Then again the validation can be tedious so keeping the authorize endpoint separate from the endpoint for logging in might be worth a thought.
The developers of Identity Server thought the same thing which is why they set up the endpoint (and endpoint validation) for you as part of the middleware. The validation uses the components that were injected (primarily the client_store, and your defined scopes) to be used by Identity Server.
After the framework validates your authorize request using your client store implementation, it will redirect the user to whichever login page you specify. The login page can be specified by changing it with the a delegate that can be passed in as the second parameter of 'AddIdentityServer' (that takes in something of type IdentityServerOptions that we'll refer to as just 'options'). In the delegate you can specify the login url of the page by changing the value of 'options.UserInteraction.LoginUrl' to the url of the login page.
After the user logs in and you call the signInAsync method on the HttpContext, you're actually supposed to redirect back to a query parameter passed to the login page referred to as the 'return_url' (which is basically the initial authorize endpoint request). This authorize endpoint further validates the cookie and will send the user back to the 'redirect_uri' (if consent on the client is set to false) with a code (if using the authorization code flow) or the id_token and optionally the access token (if using the implicit flow).
Assuming the implicit flow for simplicity, the tokens can be found in the request to the 'redirect_uri' and from there it's all up to you. Commonly the client will issue some kind of cookie (which can potentially contain the id or access token) to mark the successful authentication by the identity provider.

Azure AD reply url: how to add several urls when using openid connect auth

I'm trying to build a ASP.NET MVC app which doesn't allow access to anonymous user (with the exception of a custom URL that is to be shown to authenticated users which aren't allowed to use the app).
Now, I've register my app in the azure portal (portal.azure.com) and I'd like to use several URLs. I've added two entries:
https://localhost/test
https://www.test.com
I'm using the following code to configure authentication at startup:
public void ConfigureAuth(IAppBuilder app) {
app.SetDefaultSignInAsAuthenticationType(
CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications {
SecurityTokenValidated = VerificaUtilizadorAutenticado,
AuthenticationFailed = TrataErroAutenticacao
}
});
}
Everything seemed to be working fine, but after publishing the app, it seems like I can only use one of the URIs. I've searched and it seems like I can use the RedirectUri property of the OpenIdConnectAuthenticationOptions to set up the reply url. So, I've tried adding this to the setup:
RedirectUri = "https://localhost/test",
Unfortunately, doing that breaks everything and the browser gets stuck between my app and MS' login page. Since the user is logged in, it redirects the user back to my app. However, it seems like setting the RedirectUri prop does not generate the app's authentication cookie, so it sends the user back to the login page.
If I remove the RedirectUri, then I get redirected to the https://www.test.com site, even though I'm trying to access the https://localhost/test web app.
I'm not sure what, but I'm missing something...Can anyone help?
Thanks.
Luis
When you send a user who wants to sign in to the AAD Login Endpoint (https://login.microsoftonline.com), you will need to specify where you want the user (and the Authorization Code) to be redirected back to.
You specify this in two ways:
You must configure a Reply URL in your app's main configuration as a part of app creation.
You must specify a Reply URL in your Login URL, which exactly matches one of the URLs you configured:
From the Authorization Code Grant Flow documentation:
https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F <-- this guy
&response_mode=query
&resource=https%3A%2F%2Fservice.contoso.com%2F
&state=12345
If you do not specify a Redirect URI in your Login URL, the user will be redirected to the first URL specified in your app's registration. That doesn't sound so bad, but know that AAD treats your Reply URLs as an unordered list, so depending on the server you hit, or how data got replicated, you might observe different redirection behaviors across different sign-in attempts. That is why it is important to ALWAYS specify the redirect_uri parameter in your login endpoint.
I feel like many of your problems may be solved if you use the ADAL libraries to authenticate rather than the libraries shown in your sample code, but if you do not want to use these, then you will need to share more details like the HTTP trace of the authentication process.
Ok, after some digging, I've noticed that the problem I was having when setting the redirecturi was that I was missing...a slash (/). So, adding the / to the URL defined on the portal and putting it also in the redirecturi of the options object was enough to make it work against different URI...

google Oauth2.0 authenticate - not continue to redirect_uri

I'm trying to implement login with google to my web site.
The users can visit my site in 3 domains
1) regular link (HTTP and WWW...)
2) http://example.com - no www
3) apps.facebook.com/example - facebook app
We want to allow the user connect google in those three options.
We're using gapi (google javascript library) in order to authenticate the user.
My code looks like:
var config = {
'client_id': 'my_client_id',
'scope': 'my_scopes',
**'redirect_uri' : "https://www.example.com/oauth/",**
'immediate': immediate
};
**gapi.auth.authorize(config, function(){});**
As you can see I'm setting my redirect uri as part of the config of gapi.
We've created some popup in order to give the same uri for the three domains.
My problem is that in case I'm login to my site from the domain without the WWW, the authorize isn't working and the user isn't redirect to the redirect_uri link - which means, we don't have his token.
In case I'm removing the WWW in the redirect_uri (so it will looks like https://example.com/oauth/)
the facebook domain isn't working...
It's so frustrated..
Is anyone familiar with this kind of problem?
Any idea?
We've spent on it too many hours....
Thanks
Z
You can register multiple redirect URIs for a single client in the Google API Console so you would register one for each domain and pass the one for the currently accessed domain in the redirect_uri parameter of the authorization request. You don't need to use the same redirect URI across your domains so that should solve your state/token restoration problems.

Resources