Where is the OAuth2.0 Authorization Code stored? - oauth-2.0

I'm developing a C# application that needs to contact a web-based API. When contacting the API, the first thing it does is try to get an authorization code from an authorization server. Using RestSharp, my code is this:
static string GetAuthCode(string authUri, string clientId, string scope, Guid state, string callbackUri)
{
var client = new RestClient(authUri);
var request = new RestRequest("", Method.Post);
client.Options.MaxTimeout = -1;
request.AddParameter("client_id", clientId);
request.AddParameter("response_type", "code");
request.AddParameter("scope", scope);
request.AddParameter("state", state);
request.AddParameter("redirect_uri", callbackUri);
RestResponse response = client.Execute(request);
if (response.IsSuccessful)
{
string code = HttpUtility.ParseQueryString(response.ResponseUri.Query).Get("code");
return code;
}
else
throw new Exception(response.Content);
}
When I call this method, the response is successful, however I was expecting that the resulting authorization code would be appended to the ResponseUri property of the response (in its Query property). But it's not. The ResponseUri property is set to the authorization Uri (authUri). Am I looking in the wrong spot for the authorization code? Where can I find the actual authorization code?

It should be in the query parameters:
If the resource owner grants the access request, the authorization
server issues an authorization code and delivers it to the client by
adding the following parameters to the query component of the
redirection URI using the "application/x-www-form-urlencoded" format,
per Appendix B:
4.1 Authorization Code Grant - 4.1.2 Authorization Response

Related

Missing scope in access token - code flow

I am trying to execute Oauth2 code flow to get access token but not able to fetch built-in email scope.
Below is my setup.
I have registered an application in Azure Active Directory. Lets say app id is - APP1
I am using V2 endpoint to access 'code' from 'authorize'endpoint.
Below is piece of code
[HttpPost]
public IActionResult Index(MyModel myModel)
{
HttpClient client = new HttpClient();
var authEndpoint = "https://login.microsoftonline.com/{my-tenant-id}/oauth2/v2.0/authorize?client_id=APP1&response_type=code&scope=openid+email";
return Redirect(authEndpoint);
}
public IActionResult Callback(string code, string error)
{
Console.WriteLine("callback");
AuthenticationContext context = new AuthenticationContext("https://login.microsoftonline.com/9e8754b6-f9cd-4aed-974d-a0ec0f3ed703");
ClientCredential cc = new ClientCredential("APP1", "xxxxxxx/_");
var resource = "c4887ff4-f750-4f1b-9781-744affe6fee2";
var r = context.AcquireTokenAsync(resource,cc).Result;
var tokenEndpoint = "https://login.microsoftonline.com/9e8754b6-f9cd-4aed-974d-a0ec0f3ed703/oauth2/v2.0/token";
return Ok("");
}
Note that I am requesting two scopes openid and email
I am getting callback with appropriate code which I am trading further to retrieve access token using ADAL library.
I am getting back the access token but scope is missing in the access token . Please see below snap.
You are using the wrong method on the confidential client app object. You aren't using the code value.
So you are acquiring a token through client credentials flow, which never has scopes since it is an app-only flow.
Use the method/overload that accepts an authorisation code :)

How may I access my own protected API via IHttpClientFactory

I'm trying to access my own API via IHttpClientFactory but am getting redirected to the login page. I had this same problem via jquery but when I included credentials: 'include' it was fixed.
This is for c# / asp.net core 2.1 MVC controller. I'm using stock identity
I've tried constructing my headers to include the Authorization with Basic and base64 encoded string including my username:password. If I allow anonymous to my endpoint then my code works fine.
The form lives in a razor page and on post sends an object in the body of the request to the endpoint. If my endpoint doesn't have the [AllowAnonymous] attribute then I get redirected back to the login and/or receive a 400 bad request
string contentJson = JsonConvert.SerializeObject(content);
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Patch, baseUrl);
HttpClient client = _clientFactory.CreateClient();
httpRequest.Content = new StringContent(contentJson, Encoding.UTF8, "application/json-patch+json");
httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{yourusername}:{yourpwd}")));
HttpResponseMessage response = await client.SendAsync(httpRequest);

allow mvc5 c# webapi so that only my app can access it

I am making the api calls through the controller action method as below. The following is the working code of it.
But I want to secure the webapi so that only my application can access it. I have seen sources with login credentials
but in my case it is a public facing website with no login users.
Only the calls from my application should access it. Could anyone please suggest what can be done. or Is my current code with ValidateReferrer is suffice to handle?
[HttpGet]
[ValidateReferrer]
[ActionName("GetFind")]
[CacheOutput(ClientTimeSpan = 300, ServerTimeSpan = 300)]
public ApiQueryResponse GetFind(string query)
{
return _Worker.GetFind(query);
}
Validate Referrer in the controller has the following implementation:
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext == null)
{
throw new System.Web.HttpException("No Http context, request not allowed.");
}
else
{
if (filterContext.HttpContext.Request.UrlReferrer == null)
{
throw new System.Web.HttpException("Referrer information missing, request not allowed.");
}
else if (filterContext.HttpContext.Request.UrlReferrer.Host != filterContext.HttpContext.Request.Url.Host)
{
throw new System.Web.HttpException(string.Format("Possible cross site request forgery attack, request sent from another site: {0}", filterContext.HttpContext.Request.UrlReferrer.Host));
}
}
}
In the worker class,
public ApiQueryResponse GetFind(string query)
{
var results = GetResults(Settings.ApiKey, SetFindParameters(query), Resource);
return results;
}
private ApiQueryResponse GetResults(string apiKey, string parameterQuery, string Resource)
{
var results = new ApiQueryResponse();
if (apiKey != null && !String.IsNullOrWhiteSpace(apiKey))
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(string.Format("{0}/{1}?{2}&key={3}", WebApiUrl, Resource, parameterQuery, apiKey)).Result;
if (response.IsSuccessStatusCode)
{
var responseBodyAsText = response.Content.ReadAsStringAsync().Result;
results = JsonConvert.DeserializeObject<ApiQueryResponse>(responseBodyAsText);
}
}
}
return results;
}
Again this is the case where you have to authenticate your "application" but not users. If you check facebook/twitter/gmail api's, they have a client secret and client id to authenticate the application. But still there will be an "Authorize" call made with this id and secret for which the api returns a token and this token is used henceforth to authorize the other requests. This token will also have an expiry and there are methods to get refresh tokens.
Thus said, you have to take a call on how much security you have to implement for your api's. You could have a similar approach where your client first asks for a security token by providing the client id and secret (which should really be a secret). You can check this id and secret against your store (may be database) and if that passes the validation, you can send back a token which you could authroize using [Authroize] attribute or by custom validation.
How to create tokens should be another discussion IMO. Simple approach is mentioned here for eg- how to generate a unique token which expires after 24 hours?. There are other standard ways of generating tokens JWT/OAuth tokens.
EDIT
As a simple approach (not taking much security aspects into consideration) would be:
Create an app secret (may be a Guid value)
While sending request, take current timestamp and encrypt (have your
own encrypt and decrypt logic) the timestamp with the app secret. Lets call that encrypted value as 'token'
Pass the token in your request header (may be a custom header,say,
x-my-auth)
In the api, have a custom authorize filter
In the custom filter, overridden OnAuthroizeCore method, get the
token from request header
Decrypt the token using the same app secret and you will get the
timestamp sent from the client
If decryption is fine, then we are through the first step/ or the
token passed the first step
Additionaly, check whether the difference between the current time
and the time decrypted from token is more than 5(*you can have your
own expiry value)
If the difference is more than your expiry limit, return false which
would throw unauthorized exception back to the client (do the same if the token fails to decrypt)
The expiry check is to handle the scenario where someone hacking your
token from the request and then using it afterwards. In case if he
uses the token after your expiry, this would throw unauthorized
Consider the above logic and entire description just as a "food for thought" and DO NOT use it without proper research and understanding. My idea was to give some basic idea about the application authentication until someone really good at this writes up a really nice article in this post

How do I authorize access to ServiceStack resources using OAuth2 access tokens via DotNetOpenAuth?

I've created an OAuth2 authorization server using DotNetOpenAuth, which is working fine - I'm using the resource owner password flow, and successfully exchanging user credentials for an access token.
I now want to use that access token to retrieve data from secure endpoints in a ServiceStack API, and I can't work out how to do so. I've examined the Facebook, Google, etc. providers included with ServiceStack but it's not clear whether I should be following the same pattern or not.
What I'm trying to achieve (I think!) is
OAuth client (my app) asks resource owner ('Catherine Smith') for credentials
Client submits request to authorization server, receives an access token
Client requests a secure resource from the resource server (GET /users/csmith/photos)
The access token is included in an HTTP header, e.g. Authorization: Bearer 1234abcd...
The resource server decrypts the access token to verify the identity of the resource owner
The resource server checks that the resource owner has access to the requested resource
The resource server returns the resource to the client
Steps 1 and 2 are working, but I can't work out how to integrate the DotNetOpenAuth resource server code with the ServiceStack authorization framework.
Is there an example somewhere of how I would achieve this? I've found a similar StackOverflow post at How to build secured api using ServiceStack as resource server with OAuth2.0? but it isn't a complete solution and doesn't seem to use the ServiceStack authorization provider model.
EDIT: A little more detail. There's two different web apps in play here. One is the authentication/authorisation server - this doesn't host any customer data (i.e. no data API), but exposes the /oauth/token method that will accept a username/password and return an OAuth2 access token and refresh token, and also provides token-refresh capability. This is built on ASP.NET MVC because it's almost identical to the AuthorizationServer sample included with DotNetOpenAuth. This might be replaced later, but for now it's ASP.NET MVC.
For the actual data API, I'm using ServiceStack because I find it much better than WebAPI or MVC for exposing ReSTful data services.
So in the following example:
the Client is a desktop application running on a user's local machine, the Auth server is ASP.NET MVC + DotNetOpenAuth, and the Resource server is ServiceStack
The particular snippet of DotNetOpenAuth code that's required is:
// scopes is the specific OAuth2 scope associated with the current API call.
var scopes = new string[] { "some_scope", "some_other_scope" }
var analyzer = new StandardAccessTokenAnalyzer(authServerPublicKey, resourceServerPrivateKey);
var resourceServer = new DotNetOpenAuth.OAuth2.ResourceServer(analyzer);
var wrappedRequest = System.Web.HttpRequestWrapper(HttpContext.Current.Request);
var principal = resourceServer.GetPrincipal(wrappedRequest, scopes);
if (principal != null) {
// We've verified that the OAuth2 access token grants this principal
// access to the requested scope.
}
So, assuming I'm on the right track, what I need to do is to run that code somewhere in the ServiceStack request pipeline, to verify that the Authorization header in the API request represents a valid principal who has granted access to the requested scope.
I'm starting to think the most logical place to implement this is in a custom attribute that I use to decorate my ServiceStack service implementations:
using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;
namespace SpotAuth.ResourceServer.Services {
[RequireScope("hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
}
This approach would also allow specifying the scope(s) required for each service method. However, that seems to run rather contrary to the 'pluggable' principle behind OAuth2, and to the extensibility hooks built in to ServiceStack's AuthProvider model.
In other words - I'm worried I'm banging in a nail with a shoe because I can't find a hammer...
OK, after a lot of stepping through the various libraries with a debugger, I think you do it like this: https://github.com/dylanbeattie/OAuthStack
There's two key integration points. First, a custom filter attribute that's used on the server to decorate the resource endpoints that should be secured with OAuth2 authorization:
/// <summary>Restrict this service to clients with a valid OAuth2 access
/// token granting access to the specified scopes.</summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
public class RequireOAuth2ScopeAttribute : RequestFilterAttribute {
private readonly string[] oauth2Scopes;
public RequireOAuth2ScopeAttribute(params string[] oauth2Scopes) {
this.oauth2Scopes = oauth2Scopes;
}
public override void Execute(IHttpRequest request, IHttpResponse response, object requestDto) {
try {
var authServerKeys = AppHostBase.Instance.Container.ResolveNamed<ICryptoKeyPair>("authServer");
var dataServerKeys = AppHostBase.Instance.Container.ResolveNamed<ICryptoKeyPair>("dataServer");
var tokenAnalyzer = new StandardAccessTokenAnalyzer(authServerKeys.PublicSigningKey, dataServerKeys.PrivateEncryptionKey);
var oauth2ResourceServer = new DotNetOpenAuth.OAuth2.ResourceServer(tokenAnalyzer);
var wrappedRequest = new HttpRequestWrapper((HttpRequest)request.OriginalRequest);
HttpContext.Current.User = oauth2ResourceServer.GetPrincipal(wrappedRequest, oauth2Scopes);
} catch (ProtocolFaultResponseException x) {
// see the GitHub project for detailed error-handling code
throw;
}
}
}
Second, this is how you hook into the ServiceStack HTTP client pipeline and use DotNetOpenAuth to add the OAuth2 Authorization: Bearer {key} token to the outgoing request:
// Create the ServiceStack API client and the request DTO
var apiClient = new JsonServiceClient("http://api.mysite.com/");
var apiRequestDto = new Shortlists { Name = "dylan" };
// Wire up the ServiceStack client filter so that DotNetOpenAuth can
// add the authorization header before the request is sent
// to the API server
apiClient.LocalHttpWebRequestFilter = request => {
// This is the magic line that makes all the client-side magic work :)
ClientBase.AuthorizeRequest(request, accessTokenTextBox.Text);
}
// Send the API request and dump the response to our output TextBox
var helloResponseDto = apiClient.Get(apiRequestDto);
Console.WriteLine(helloResponseDto.Result);
Authorized requests will succeed; requests with a missing token, expired token or insufficient scope will raise a WebServiceException
This is still very much proof-of-concept stuff, but seems to work pretty well. I'd welcome feedback from anyone who knows ServiceStack or DotNetOpenAuth better than I do.
Update
On further reflection, your initial thought, to create a RequiredScope attribute would be a cleaner way to go. Adding it to the ServiceStack pipeline is as easy as adding the IHasRequestFilter interface, implementing a custom request filter, as documented here: https://github.com/ServiceStack/ServiceStack/wiki/Filter-attributes
public class RequireScopeAttribute : Attribute, IHasRequestFilter {
public void RequireScope(IHttpRequest req, IHttpResponse res, object requestDto)
{
//This code is executed before the service
//Close the request if user lacks required scope
}
...
}
Then decorate your DTO's or Services as you've outlined:
using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;
namespace SpotAuth.ResourceServer.Services {
[RequireScope("hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
}
Your RequireScope custom filter would be almost identical to ServiceStack's RequiredRoleAttribute implementation., so use it as a starting point to code from.
Alternately, you could map scope to permission. Then decorate your DTO or service accordingly (see SS wiki for details) for example:
[Authenticate]
[RequiredPermission("Hello")]
public class HelloService : Service {
public object Any(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
Normally ServiceStack calls the method bool HasPermission(string permission) in IAuthSession. This method checks if the list List Permissions in IAuthSession contains the required permission, so, in a custom IAuthSession you could override HasPermission and put your OAuth2 scopes checking there.

GetClientAccessToken having clientIdentifier overwritten to null by NetworkCredential

I've been trying to get the GetClientAccessToken flow to work with the latest release 4.1.0 (via nuget), where I'm in control of all three parties: client, authorization server and resource server.
The situation I have started to prototype is that of a Windows client app (my client - eventually it will be WinRT but its just a seperate MVC 4 app right now to keep it simple), and a set of resources in a WebAPI project. I'm exposing a partial authorization server as a controller in the same WebAPI project right now.
Every time (and it seems regardless of the client type e.g. UserAgentClient or WebServerClient) I try GetClientAccessToken, by the time the request makes it to the auth server there is no clientIdentifier as part of the request, and so the request fails with:
2012-10-15 13:40:16,333 [41 ] INFO {Channel} Prepared outgoing AccessTokenFailedResponse (2.0) message for <response>:
error: invalid_client
error_description: The client secret was incorrect.
I've debugged through the source into DNOA and essentially the credentials I'm establishing on the client are getting wiped out by NetworkCredential.ApplyClientCredential inside ClientBase.RequestAccessToken. If I modify clientIdentifier to something reasonable, I can track through the rest of my code and see the correct lookups/checks being made, so I'm fairly confident the auth server code is ok.
My test client currently looks like this:
public class AuthTestController : Controller
{
public static AuthorizationServerDescription AuthenticationServerDescription
{
get
{
return new AuthorizationServerDescription()
{
TokenEndpoint = new Uri("http://api.leave-now.com/OAuth/Token"),
AuthorizationEndpoint = new Uri("http://api.leave-now.com/OAuth/Authorise")
};
}
}
public async Task<ActionResult> Index()
{
var wsclient = new WebServerClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var appclient = new DotNetOpenAuth.OAuth2.UserAgentClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var cat = appclient.GetClientAccessToken(new[] { "https://api.leave-now.com/journeys/" });
// Acting as the Leave Now client we have access to the users credentials anyway
// TODO: CANNOT do this without SSL (turn off the bits in web.config on BOTH sides)
/*var state = client.ExchangeUserCredentialForToken("kieranbenton", "password", new[] { "https://api.leave-now.com/journeys/" });
// Attempt to talk to the APIs WITH the access token
var resourceclient = new OAuthHttpClient(state.AccessToken);
var response = await resourceclient.GetAsync("https://api.leave-now.com/journeys/");
string sresponse = await response.Content.ReadAsStringAsync();*/
// A wrong one
/*var wresourceclient = new OAuthHttpClient("blah blah");
var wresponse = await wresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string wsresponse = await wresponse.Content.ReadAsStringAsync();
// And none
var nresourceclient = new HttpClient();
var nresponse = await nresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string nsresponse = await nresponse.Content.ReadAsStringAsync();*/
return Content("");
}
}
I can't figure out how to prevent this or if its by design what I'm doing incorrectly.
Any help appreciated.
The NetworkCredentialApplicator clears the client_id and secret from the outgoing message as you see, but it applies it as an HTTP Authorization header. However, HttpWebRequest clears that header on the way out, and only restores its value if the server responds with an HTTP error and a WWW-Authenticate header. It's quite bizarre behavior on .NET's part, if you ask me, to suppress the credential on the first outbound request.
So if the response from the auth server is correct (at least, what the .NET client is expecting) then the request will go out twice, and work the second time. Otherwise, you might try using the PostParameterApplicator instead.

Resources