RFC 6749 Authentication with ServiceStack - c#

It looks like ServiceStack only accepts session-based authentication. I was reading through https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization and I couldn't find anything describing how to do what I want.
I also looked at http://enehana.nohea.com/general/customizing-iauthprovider-for-servicestack-net-step-by-step/ but that also is session-based.
What I would like to do, is very similar to how WebAPI works with Individual User Accounts.
I want to send this to the API:
POST http://localhost:49436/Token HTTP/1.1
User-Agent: Fiddler
Host: localhost:49436
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
grant_type=password&username=Alice&password=password123
Then, if the user is found in my custom authentication method, it returns this:
{
"access_token":"boQtj0SCGz2GFGz[...]",
"token_type":"bearer",
"expires_in":1209599,
"userName":"Alice",
".issued":"Mon, 14 Oct 2013 06:53:32 GMT",
".expires":"Mon, 28 Oct 2013 06:53:32 GMT"
}
Then, the client app can just send the access_token on subsequent requests by appending a value like this to the HTTP request:
Authorization: Bearer boQtj0SCGz2GFGz[...]
Is this possible in ServiceStack?
Edit: Implementation using .NET's WebAPI: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

Related

Fortify Allowed header option

I am building a RESTful API. When the client uses an unsupported method such as GET on a resource that does not supports it, I am returning a 405 with the Allow header which lists the allowed methods:
Response
Status Code: 405 Method Not Allowed
Allow: DELETE, PUT, POST
Connection: keep-alive
Date: Mon, 08 Apr 2013 00:19:26 GMT
Fortify display insecure HTTP method(s) on the web server.
How fortify determine insecure Http methods ?

401 Unauthorized - token not being accepted

I'm successfully using the Graph API for a variety of things but I need to access to the OneNote API to perform student and teacher add/remove operations on Class Notebooks. When I request a token the same way that I do for Graph with the https://www.onenote.com resource it provides one but when I try to use it to access the OneNote API no matter what (valid) request I send I get 401 - "The request does not contain a valid authentication token."
I've tried using the v1.0 endpoint to generate a token instead with the same results.
My token requests:
POST https://login.microsoftonline.com/{my tenant}/oauth2/v2.0/token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Host: login.microsoftonline.com
Content-Length: 213
Expect: 100-continue
Connection: Keep-Alive
grant_type=client_credentials&client_id={my appid}&client_secret={my secret}&tenant={my tenant}&scope=https%3A%2F%2Fwww.onenote.com%2F.default
OR
POST https://login.microsoftonline.com/{my tenant}/oauth2/token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Host: login.microsoftonline.com
Content-Length: 161
Expect: 100-continue
grant_type=client_credentials&client_id={my appid}&client_secret={my secret}&resource=https%3A%2F%2Fwww.onenote.com
Both return something containing an access_token, like:
{"token_type":"Bearer","expires_in":"3600","ext_expires_in":"3600","expires_on":"1543513719","not_before":"1543509819","resource":"https://www.onenote.com","access_token":"{a token}"}
Request:
GET https://www.onenote.com/api/v1.0/myorganization/groups/{group id}/notes/ HTTP/1.1
ContentType: application/json
Authorization: Bearer {token returned from /token request}
Cache-Control: no-store, no-cache
Host: www.onenote.com
Response:
code=40001
message=The request does not contain a valid authentication token.
For reference, this question is basically a follow-up to: Adding Students with the API and Class Notebook
You're on the right track.
Resource is the right way with the 1.0 auth endpoint.
Scopes need to be registered on the app portal, so you'll need to go back in and add OneNote scopes in the portal.
I'm not 100% sure, but IIRC the resource for onenote might require a trailing '/'.

See SOAP format into web services with fiddler

I create a web services and a ConsoleApplication to consume it. I am using fiddler to see the traffic, i was hoping that the request and response was SOAP but that's don't happend, only the request was SOAP, not the response.
How can i force to my service that respond using soap?
This is the raw http header obtained:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 17 Nov 2014 20:19:22 GMT
Content-Length: 311
The respond is in binary.
My web-service was created adding a Web Services item to ASP.NET Empty Web Application project, and i don't modified, later I published in IIS.
My consumer is very simple too. I just add the service reference and create an instance.
var binding = new BasicHttpBinding();
var endpointAddress = new EndpointAddress("http://172.20.48.59/web-services/MyWebService.asmx");
var serviceRefWithoutConfig = new ServiceReference1.MyWebServiceSoapClient(binding, endpointAddress);
Console.WriteLine(serviceRefWithoutConfig.HelloWorld());
The HTTP response in question is compressed with GZIP.
What happens after you click the big yellow bar in Fiddler that says Response is encoded and may require decoding before inspection. Click here to transform.?
If you are creating something new, I strongly suggest you look at using WebAPI for something like this.
It's much easier to control the output of your methods, and the resulting service will be easier to consume from mobile platforms, should the need arise in future.

Fundamental Misunderstanding About CORS and Ajax Call

I have code that works, but I'm having a difficult time making the connection as to why it works.
I have code in an AngularJS factory function that makes this call:
$http.get('http://webServerName/PrestoWebApi/api/apps/')
And this is the Web API controller (C#):
[EnableCors(origins: "http://webServerName", headers: "*", methods: "*")]
public class AppsController : ApiController
The source of the call would be a user's computer, for example, a laptop with the name JoesLaptop. And that laptop could run anywhere. (Currently, this is all running inside one LAN, but the user could be anywhere.)
So why does specifying the web server name within the EnableCors attribute work? Isn't the request coming from the browser on Joe's laptop and not from the web server itself?
Edit
If I remove the EnableCors attribute, I get this error in the F12 tools in the browser:
XMLHttpRequest cannot load http://webServerName/PrestoWebApi/api/apps/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://webServerName' is therefore not allowed access.
Edit 2
Request:
GET http://fs-6103.fs.local/PrestoWebApi/api/apps/ HTTP/1.1
Host: fs-6103.fs.local
Connection: keep-alive
Accept: application/json, text/plain, */*
Origin: http://fs-6103
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
Referer: http://fs-6103/PrestoWebApi/app/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://fs-6103
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 31 Oct 2014 18:30:05 GMT
Content-Length: 2931171
If webServerName is rendering an HTML page that is starting an asynchronous request to webServerName, then CORS doesn't apply and your server will serve that resource anyway.
I'm pretty sure that must be your case.
UPDATE
Based on the latest edits of the question and the comments that the OP has made bellow this answer, this is what must be happening.
The HTTP server that it's serving both the main HTML page and the API resource is the same, therefore there shouldn't be any need to EnableCORS. However, according to the headers of the Request the page is being served from http://fs-6103 and the $http.get is made to http://fs-6103.fs.local. That should explain everything.
UPDATE 2
Ok, I'm willing to bet that this is what's happening here:
The main page is being served by http://fs-6103
The $http.get is made towards: http://fs-6103.fs.local/
So far I'm not speculating, this is what the request is saying
The OP must have [EnableCors(origins: "http://fs-6103", headers: "*", methods: "*")] set into the API controller.
When this is disabled the OP is getting the error: No 'Access-Control-Allow-Origin' header is present on the requested resource, as it should be expected. And when the OP enables it everything works as expected.
Browsers/clients handle the security, and generally restrict things to single origin, meaning they only accept stuff from the server they made the request to. Enabling cors in the header (ACAO) or wherever lets that server tell the browser, "hey those other Cross origin resources are with me." The browser will generally go along with that.

Score API - update request returns HTTP 403 error, (#200) User cannot access this application

I'm developing a game on Facebook and having a problem to update the scores of the players.
The application receives HTTP ERROR 403 from Facebook as a response to the update score Graph API call. When I replay the same HTTP post request from other machines it passes without any error.
More information:
Players are requested for publish_actions during registration
The application is registered as a game
The admins of the application don't get the error from FB
The servers which run the applications are behind a load balance
This can't be networking issue since some update requests pass, this can't also be permission issue since the request is passed when executed from other machines.
Does anyone have an idea how to solve the problem or give me a direction to keep on investigating?
HTTP session as recorded by fiddler( XXX is replacing the application access token):
POST /100000868887295/scores/?score=1&access_token=XXX HTTP/1.1
User-Agent: Fiddler
Host: graph.facebook.com
HTTP/1.1 403 Forbidden
Access-Control-Allow-Origin: *
Cache-Control: no-store
Content-Type: text/javascript; charset=UTF-8
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Pragma: no-cache
WWW-Authenticate: OAuth "Facebook Platform" "insufficient_scope" "(#200) User cannot access this application"
X-FB-Rev: 677653
X-FB-Debug: gxaao2ZoKOtcQNpLCO4Wh9kXigIhnGByugWQOlg0Y3Y=
Date: Sat, 24 Nov 2012 15:16:03 GMT
Connection: keep-alive
Content-Length: 101
{"error":{"message":"(#200) User cannot access this application","type":"OAuthException","code":200}}
Problem solved.
We had country restrictions defined in the Facebook application back office.
Since our server is not located in one of the allowed countries the requests sent from that server where rejected by Facebook.
Once we removed the country restrictions everything started to work.
The score api requires that you use an application access token to post the scores.

Categories