How do you get the client calling URL from ServiceStack Service base class? - servicestack

I need to log the requesting (client) URL for each request to the service.
I looked through the Request object on the Service base class and the only URL recorded is the service URL requested. Where can I get the requesting caller URL?

You can access the context of the request in your base.Request and base.Response properties in your Service class, e.g:
var requestUrl = base.Request.AbsoluteUri;
var referrerUrl = base.Request.UrlReferrer;

Related

what is the code for getting auth code from azure in IBM BPM

I am trying to create rest request using Call Multipart form data REST API service in REST API toolkit. It requires apiURL, HTTPHEADER, PARAMETERtoPOST, httpMethod (using GET). I defined all the parameters(client id, client secret, response type (code), scope and response mode (query)) and httpheader - > Content -Type is application/x-www-form-urlencoded.
But in the response message I dont get the authcode even though when I create whole URL directly including parameters , I get the authcode but without Redirect URI. If I include redirect uri, it shows me that URI is not configured even though system admin for that showed me its configured.
So am I missing any parameters or anything else?

How to get SOAP user name in WCF Service when using UserNamePasswordValidator?

A SOAP request is made to my WCF service. How can I access the user name used in the request's Envelope.Header.Security.UserNameToken.Username field?
I am using a custom UserNamePasswordValidator to check the credentials.
In my case System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name held the user name (from the request's SOAP header) used in the UserNamePasswordValidator.Validate method. It can be accessed in the WCF Service class/method.
public class Service1 : IService1
{
public Response ServiceMethod(Request request)
{
string userName = System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name;
// ...
}
}

Testing an Azure Hybrid Connection using SoapUI

I have an Azure Hybrid Connection that's supposed to connect to some on-prem service and expose it to my app services. However, the setup is failing somewhere, and I'm trying to narrow down exactly what the problem is.
As part of this process (and because it would be useful to me in the future) I'm trying to make a call to the underlying on-prem service using SoapUI, but the initial GET request that's supposed to give me the WSDL is instead giving me an authentication error:
GET https://my-relay.servicebus.windows.net/my-endpoint/my-service.svc?wsdl
{
"error": {
"code": "TokenMissingOrInvalid",
"message": "MissingToken: Relay security token is required. TrackingId:b58c004c-e0e6-4dd0-a233-e0d304795e4e_G21, SystemTracker:my-relay.servicebus.windows.net:my-endpoint/my-service.svc, Timestamp:2019-03-05T10:17:26"
}
}
From where do I get the Relay security token, and how do I tell SoapUI about it?
This guide may give you the answers you need.
https://www.soapui.org/soap-and-wsdl/authenticating-soap-requests.html
I suspect your normal app automatically accesses the webservice as the current user on the current system. If so, I believe you should look at the NTLM authentication.
You need to create a security token and pass it in the header of your request.
Something like this:
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(KeyName, Key);
var uri = new Uri(string.Format("https://{0}/{1}", RelayNamespace, ConnectionName));
var token = (await tokenProvider.GetTokenAsync(uri.AbsoluteUri, TimeSpan.FromHours(1))).TokenString;
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = uri,
Method = HttpMethod.Get,
};
request.Headers.Add("ServiceBusAuthorization", token);
var response = await client.SendAsync(request);
For SOAPUI, you would add the resultant token value in a header named "ServiceBusAuthorization."

How to store access token? (Oauth 2, Auth code flow)

From what i understand the purpose of the Authorization Code flow is to exchange the auth code for access token. This exchange happens between the server which serves the page and authorization server so that the actual access token is not exposed to the client user.
How should the page server store the access token once it is obtained? I was learning from a Pluralsight example in which there is this part of code:
public static HttpClient GetClient()
{
HttpClient client = new HttpClient();
var accessToken = RequestAccessTokenAuthorizationCode();
client.SetBearerToken(accessToken);
client.BaseAddress = new Uri(IdentityConstants.API);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
private static string RequestAccessTokenAuthorizationCode()
{
// did we store the token before?
var cookie = HttpContext.Current.Request.Cookies.Get("ClientMVCCookie.AuthCode");
if (cookie != null && cookie["access_token"] != null && !string.IsNullOrEmpty(cookie["access_token"]))
{
return cookie["access_token"];
}
// no token found - request one
// we'll pass through the URI we want to return to as state
var state = HttpContext.Current.Request.Url.OriginalString;
var authorizeRequest = new IdentityModel.Client.AuthorizeRequest(
IdentityConstants.AuthEndoint);
var url = authorizeRequest.CreateAuthorizeUrl(IdentityConstants.MVCClientSecret, "code", "management secret",
IdentityConstants.MVCAuthCodeCallback, state);
HttpContext.Current.Response.Redirect(url);
return null;
}
}
This will cause each request to check if there is an access token stored in the cookie. If not then the flow will be initiated. The callback looks like this:
public class CallbackController : Controller
{
// GET: STSCallback
public async Task<ActionResult> Index()
{
// get the authorization code from the query string
var authCode = Request.QueryString["code"];
// with the auth code, we can request an access token.
var client = new TokenClient(
IdentityConstants.TokenEndoint,
"mvc_client_auth_code",
IdentityConstants.MVCClientSecretAuthCode);
var tokenResponse = await client.RequestAuthorizationCodeAsync(
authCode,
IdentityConstants.MVCAuthCodeCallback);
// we save the token in a cookie for use later on
var cookie = Response.Cookies["ClientMVCCookie.AuthCode"];
cookie.Expires = DateTime.Now.AddMinutes(1);
cookie["access_token"] = tokenResponse.AccessToken;
// get the state (uri to return to)
var state = Request.QueryString["state"];
// redirect to the URI saved in state
return Redirect(state);
}
}
Doesn't storing the access token in the cookie defeath the whole purpose of the authorization code flow? The cookie will be transmitted to the client browser thus exposing it to the client? Am i missing something? It this is not the correct way to store the token, how should it be stored?
The client, in OAuth terminology, is the component that makes requests to the resource server, in your case, the client is the server of a web application (NOT the browser).
Therefore, the access token should be stored on the web application server only. It should not be exposed to the browser, and it doesn't need to, because the browser never makes any direct requests to the resource server. It talks to the web application server instead, which in turn makes requests to the resource server using the access token.
How the browser authenticates itself with the web application server has nothing to do with OAuth 2.0. For example, it might be a regular session cookie, and the web application server might associate each session or each user with an access token.
The token request, which exchanges the authentication code for an access token, is done by the web application server, and the web application server should authenticate itself with the authorization server (e.g., using a shared client_secret).
Authorization code flow ensures that the client can be authenticated, which protects against malicious clients posing as legitimate clients. Not all web application clients have a server component, and in some cases, requests to the resource server are made directly by JavaScript code in the browser. In such situations, the browser is the client, and the access token must be stored by the browser (in a JavaScript variable, local storage or a cookie). In this case, the client cannot be authenticated (but a reasonable amount of security may be achieved by using TLS and the server redirecting only to registered endpoint URLs).
Recommended reading regarding OAuth 2.0 security: https://www.rfc-editor.org/rfc/rfc6819#section-4.3.3 (RFC 6819)
The cookie is never exposed to the browser. It is part of the response returned from the authorization server to the client, which itself is a server, not a browser. The CallbackController, which implements the redirection endpoint, extracts the cookie from the response.
The cookie is never passed on to the browser. How the browser authenticates itself with the client's application server is not shown in your sample code, and it is not part of OAuth.
The authorization server could store the token in the request body (e.g., in JSON format) rather than in a cookie. However, this makes no difference, because the client can see and process the entire response anyway.
For details, see my other answer: https://stackoverflow.com/a/44655679/2279059
Side note: The CallbackController uses state to store a final URL to redirect the browser to. This is non-standard but works. However, state is actually meant to protect the redirection endpoints against CSRF attacks. The CallbackController does not validate state but blindly redirects to whatever URL was given. Probably this detail was left out, because the code was meant as an example. However, it shows that this code is probably not entirely production-ready.
If you are going to request a rest resource from the browser, the flow you need is Implicit Grant. Check this Auth0 post to decide between the flows https://auth0.com/docs/api-auth/which-oauth-flow-to-use. If you want to use the access token from server you should store the Authorization code and generate an access token every time you need it, access token is not intended to live more than 5 minutes, you don't need to store it

How do you call an authenticated ServiceStack service once the client is authenticated using OAuth?

Lets say I have a web client (i.e. MVC 4 client) that authenticates users using an oAuth provider (i.e. Facebook, Google etc).
I want to call another web service in my client logic, and that web service also authenticates with oAuth providers.
What would the web service request look like from the client? What do I need to pass to the web service?
I suggest you review this question, How do I authorize access to ServiceStack resources using OAuth2 access tokens via DotNetOpenAuth?. The poster provided his final solution, including a link to a sample solution, which he has graciously open sourced. The client side code, for his solution, looks like this:
// 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);
A similar solution is provided here: https://stackoverflow.com/a/13791078/149060 which demonstrates request signing as per OAuth 1.0a
var client = new JsonServiceClient (baseUri);
client.LocalHttpWebRequestFilter += (request) => {
// compute signature using request and a previously obtained
// access token
string authorization_header = CalculateSignature (request, access_token);
request.Headers.Add ("Authorization", authorization_header);
};
var response = client.Get<MySecuredResponse> ("/my/service");
You will, of course, need to adjust to fit the requirements of your OAuth providers, i.e. signing, token, etc.

Resources