I've been trying to add the OAuth2 provider for Google to a proof of concept application built on ServiceStack however I keep getting the following error when I try to initiate a login...
This method requires a current HttpContext. Alternatively, use an overload of this method that allows you to pass in information without an HttpContext`enter code here`
[Auth: 11/21/2013 10:29:25 PM]: [REQUEST: {provider:googleoauth}] System.InvalidOperationException: This method requires a current HttpContext. Alternatively, use an overload of this method that allows you to pass in information without an HttpContext. at DotNetOpenAuth.Requires.ValidState(Boolean condition, String message) at DotNetOpenAuth.Messaging.Channel.GetRequestFromContext() at DotNetOpenAuth.OAuth2.WebServerClient.ProcessUserAuthorization(HttpRequestBase request) at ServiceStack.Authentication.OAuth2.OAuth2Provider.Authenticate(IServiceBase authService, IAuthSession session, Auth request) at ServiceStack.ServiceInterface.Auth.AuthService.Authenticate(Auth request, String provider, IAuthSession session, IAuthProvider oAuthConfig) at ServiceStack.ServiceInterface.Auth.AuthService.Post(Auth request) at ServiceStack.ServiceInterface.Auth.AuthService.Get(Auth request) at lambda_method(Closure , Object , Object ) at ServiceStack.ServiceHost.ServiceRunner`1.Execute(IRequestContext requestContext, Object instance, TRequest request)
I've also downloaded the demo app SocialBootstrapApi and added the Google Oauth2 provider to it and was able to get it to work. I've copied over the config from the web.config into the app.config file of the self hosted project but it still doesn't work.
Any help would be great!
Thanks for the help.
The ServiceStack.AuthWeb.Tests is an ASP.NET WebHost showing all the ServiceStack AuthProviders working within a single app.
Note the OAuth2 providers use additional configuration specified in the Web.config which requires that you register your own application to get your Consumer Key and Secret for your app. For testing purposes you can use the ServiceStack Test keys already embedded in the Web.config.
The OAuth2 section in the Authentication wiki provides the urls where you can register your application for each provider.
Related
I'm struggling to understand some of this...
For some background, I am running a .NET Framework 4.8 ASP.NET MVC 5 Web UI application on an AWS EC2 instance behind an application load balancer. The load balancer is configured to authenticate via Azure AD.
I am fairly new to this world of Authentication in web applications so I'm trying to find examples of similar configurations or documentation describing my specific setup but mostly all I find is examples citing .NET Core (not .NET Framework).
Based on this documentation (Authenticate users using an Application Load Balancer), I know I am supposed to receive the headers X-Amzn-Oidc-Accesstoken, X-Amzn-Oidc-Identity, and X-Amzn-Oidc-Data from the load balancer. And indeed, if I check the headers, they are populated:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var amznOidcData = Request.Headers.Get("X-Amzn-Oidc-Data");
var amznOidcIdentity = Request.Headers.Get("X-Amzn-Oidc-Identity");
var amznAccessToken = Request.Headers.Get("X-Amzn-Oidc-Accesstoken");
logger.Debug($"X-Amzn-Oidc-Data => {amznOidcData}");
logger.Debug($"X-Amzn-Oidc-Identity => {amznOidcIdentity}");
logger.Debug($"X-Amzn-Oidc-Accesstoken => {amznAccessToken}");
}
Great! Now, I know that the X-Amzn-Oidc-Data header contains a JWT containing my claims. I have found examples on how to decode the content of that header and I can pull out my ClaimsIdentity. Ok, I'm getting there! But, where exactly is the proper place to do this? Currently, I have this code inside my Application_PostAuthenticateRequest method within Global.asax.cs. I pull the ClaimsIdentity from the JWT and assign it to HttpContext.Current.User. Boom Request.IsAuthenticated is now showing true. Calls to Controllers with [Authorize()] are now succeeding when I load my first View.
However, this just not feel right. Yes, it seems to work for that first request to display Home/Index...but now, when the client-side javascript on that page tries to perform a callback to refresh some of the data in, let's say, a grid, I get CORS errors coming back from login.microsoft.com. Specifically:
Access to XMLHttpRequest at 'https://login.microsoftonline.com/...' (redirected from
'https://example.net/Home/Something') from origin 'https://example.net' has been blocked by CORS
policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
My assumption here is that those javascript callbacks are not recognizing that the application has already authenticated and so is trying again, on each call, to re-authenticate. I'm not sure what to do here short of marking each Controller method that would potentionally be called from the client as [AllowAnonymous()]. That seems like overkill and not what one should do.
So, my questions are these:
Where should I properly be reading in the JWT from the load balancer?
How do I properly configure my application to read that ClaimsIdentity from that JWT?
How do I ensure that client-side javascript calls to my application don't each need full callback to Microsoft to re-authenticate?
On that 2nd question, I've read a bunch of examples describing using OWIN middleware to authenticate against Azure AD...but how do I use the middleware with the JWT I already have from AWS?
Help me StackOverflow, you're my only hope...
I would like to know that how [Authorize] attribute recognize that this user is authenticate?
If user is valid then we call FormsAuthentication.SetAuthCookie() method and as per MSDN this method:
Creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication.
Is [Authorize] attribute checks authentication ticket or cookies collection?
[Authorize] does not deal with any authentication mechanism itself. It merely looks in the users IIdentity for the IsAuthenticated flag. It will also look in the users IsMemberOf method, for authorization based on roles.
All the work to decode the authentication ticket is done in the early stages of the app pipeline, which sets those flags. By the time the Authorization Attribute methods are called, all that work has already been done and is stored in the users runtime data.
You can easily check the source code for the Authorize attribute, and you will see that it's quite simple in nature. It just returns true or false based on some simple lookups.
It's become more complicated in .net core, where it's based on policies and what not, but the original MVC implementation was quite simple.
My answer relates to ASP.NET Core I'm not sure if you asked about classic ASP.NET but this should be similar.
There's a middleware that you have to add for [Authorize] to work. ASP.NET Core provides this middleware out of the box and you can add your custom authentication handlers too.
You can check how it's implemented by reading: https://github.com/aspnet/Security/tree/dev/src
For example you want to use JWT bearer authentication, you have to add JWT bearer middleware, this is simply extension of AuthenticationBuilder: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerExtensions.cs which calls AddScheme under the hood.
You want to use cookie based authentication you just call AddCookie which is also extension that calls AddScheme under the hood: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.Cookies/CookieExtensions.cs
Usage of it is documented here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1
See also Using the [Authorize] Attribute
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action.
If you are interested how this filter works under the hood you can check it here.
You must be authenticated before you can be authorized, this is the logic responsible for it: https://github.com/aspnet/Security/blob/644f34e90d35b369efdce9c11ab1db42e0a7f4a7/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs#L91
In summary
how [Authorize] attribute knows that this user is authenticated.
Authorize attribute alone doesn't know if this user is authenticated. This is handled by authentication middleware and depends stricly on the scheme it tries to authenticate with. It simply tries to authenticate with schemes you have added(cookie,jwt etc.) by calling HttpContext.AuthenticateAsync which is simply calling AuthenticationService.AuthenticateAsync under the hood and sets HttpContext.User from the result ClaimsPrincipal, which is simply result from schema handler like jwt handler for instance. I think this should give you more in-depth idea how this works.
Generally if you're starting new project I don't recommend using classic ASP.NET and prepare for the future with .NET Core as everything is now going in this direction. ASP.NET 5 ( I also refer to it as "classic") is pretty much dead now.
My Web API (2.0) services and MVC (4.0) code is running inside same web application. I call Web APIs from MVC application as usual HTTP service call.
I have added IAuthenticationFilter in the WebApi pipeline because I want to do some security related validations before any Web Api controller is executed. I keep security related data (E.g. TokenId) in the HttpContext.Current.Session. E.g. HttpContext.Current.Session["TokenId"].
Somehow data kept in the Session is available when I access it from MVC controller or from WebApi controller. But it's NOT available in the AuthenticationFilter when filter runs for the first time i.e. when very first WebApi call is done from MVC application.
Can you tell me when Session is populated by WebApi infrastructure and why values stored in the Session are unavailable during first call ? Note that they are available from the second call onwards!
I have already verified that Session has values in it. Its just that they are not available in the filter during it's first execution.
SessionStateBehavior.Required is already set correctly from WebApi from Global.asax.
(I know that Session is not recommended but I have to use it for now.)
Try with this snippet in global.ascx.cs (mine is in VB but just translate the code)
Protected Sub Application_BeginRequest()
if IsWebApiRequest() Then
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required)
end if
end sub
Private function IsWebApiRequest() as Boolean
return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Contains("api")
end function
For me it works and makes the session available in the AuthenticationFilter
I've been trying to follow examples of how to configure Web Api to use bearer tokens with Asp.Net Identity 2.0, and I've run into a hiccup. Following this tutorial http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api it states that i should be able to post to http://{servername}/Token to get a bearer token. when i do this, i get an exception for Castle Windsor when it tries to resolve Token as a controller.
What i'm trying to accomplish overall is to sign in using using the canned Account controller and then retrieve a token. I am trying to use both cookies and bearer tokens.
is this the right approach to use the default account controller to authenticate?
if this is not the correct approach, should i follow the tutorial more closely and have the user sign-in against an api controller?
what do i need to do for my IoC configuration to make sure my end points resolve?
Authorization in WebApi should be handled in a MessageHandler, not at controller level.
You should create a MessageHandler responsable to verify an OAuth Berarer Token: that message handler may(should) resolved by your IoC and than configurated in the WebApi pipeline.
public static void RegisterGlobalHandlers(HttpConfiguration config, IWindsorContainer container)
{
var authorizationMessageHandler = container.Resolve<AuthorizationMessageHandler>();
config.MessageHandlers.Add(authorizationMessageHandler);
}
DotNetOpenOAuth is a great place to start: have a look to the mvc5 sample/message handler implementation.
In my web project I have to serve ads through our openx server but after searching for documentation on how to implement openx's API on .NET, I haven't found anything.
Does anyone know how to implement their API on .NET and how to serve ads through it?
Documentation is appreciated.
Note: I have done my searches and I didn't find anything relating this matter. Using their own API is a priority to third parties API.
EDIT:
Public Class OpenXAdsProcessor
Dim session As OpenXNet.ISession
Dim s As IOpenXProxy
Public Sub New()
s = CookComputing.XmlRpc.XmlRpcProxyGen.Create(Of IOpenXProxy)()
s.Url = "ourserverurl/www/api/v1/xmlrpc/LogonXmlRpcService.php"
s.XmlRpcMethod = "logon"
session = New SessionImpl(s, "username", "password")
End Sub
End Class
Above I am implementing OpenX API. Right now I'm waiting to get permissions for my user because the server returned "Server returned a fault exception: [801] User must be OA installation admin" on my attempt to login.
Will the above code suffice to make use of your API?
I'm the author of OpenX.NET. If you just need to serve OpenX ads in a web application, you don't need to use these API bindings. Just place the OpenX javascript in your web page.
If you really need to use the API for other kind of scenarios and are new to OpenX, I recommend first getting familiar with OpenX concepts, see the OpenX Developer Zone. Then see some OpenX.NET tests. OpenX.NET is a 1-to-1 mapping to OpenX entities and methods.
EDIT: unless you want to debug something or really know what you're doing, you never need to handle the proxy directly. Simply use the session constructor:
SessionImpl(string username, string password, string url)
The URL is the root URL for the OpenX v2 API, e.g. http://localhost:10002/openx/api/v2/xmlrpc/, see the sample app.config in the tests.
There are some bindings available for .NET.