i have a SimplaKeyAuthorizeFilter,in the filter,will throw 401
public SimpleKeyAuthorize(IHttpRequest req, IHttpResponse res, object obj, bool isDebugMode){
throw new UnauthorizedAccessException("lack sign info!");
}
in the apphost:
this.ExceptionHandler = (httpReq, httpRes, operationName, ex) =>{
DtoUtils.CreateErrorResponse(httpReq, ex, new ResponseStatus() { ErrorCode = ex.ToErrorCode(), Message = ex.Message });
httpRes.Write(ex.ToErrorCode());
httpRes.EndRequest(skipHeaders:false);
};
........
this.RequestFilters.Add((req,res,obj)=>{
new SimpleKeyAuthorize(req,res,obj,false);
});
but when i call the service,the httpstatuscode is 200,is not 401,why?
HTTP/1.1 200 OK (why not 401?)
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 14 Mar 2014 05:56:30 GMT
Content-Length: 27
UnauthorizedAccessException
This is happening because ServiceStack only maps exceptions to status code within the scope of the service.
Request bindings and filters are considered outside this scope, which is why they trigger a separate exception handler method. See the section Customized Error Handling in the Error Handling documentation.
If you throw an exception here you will need to set the response status code yourself.
httpRes.StatusCode = HttpStatusCode.Unauthorized;
Hope this helps.
Related
I have started using Azure.Storage.Blobs nuget in my Function Apps.
Only problem it causes at the moment is that it logs a lot of unnecessary stuff that I don't need to see. Mainly Request and Response messages that fill a large amount of my application insights now.
Is there a way to remove those without touching any other logs? I would assume you should be able to do something from host.json, but so far nothing has worked for me to tackle this problem.
Example logs that I get:
Request [f42fdb4b-8d26-418d-ae67-1d4e79bdabd6] GET <resource_address> x-ms-version:2021-08-06 Accept:application/xml x-ms-client-request-id: x-ms-return-client-request-id:true User-Agent:azsdk-net-Storage.Blobs/12.13.0,(.NET 6.0.8; Microsoft Windows 10.0.14393) x-ms-date:Thu, 29 Sep 2022 19:07:43 GMT Authorization:REDACTED client assembly: Azure.Storage.Blobs
Response [f42fdb4b-8d26-418d-ae67-1d4e79bdabd6] 200 OK (00.0s) Accept-Ranges:bytes ETag:"" Server:Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0 x-ms-request-id: x-ms-client-request-id:<request_id> x-ms-version:2021-08-06 x-ms-version-id:REDACTED x-ms-is-current-version:REDACTED x-ms-creation-time:Thu, 29 Sep 2022 19:07:39 GMT x-ms-lease-status:unlocked x-ms-lease-state:available x-ms-blob-type:BlockBlob x-ms-server-encrypted:true Date:Thu, 29 Sep 2022 19:07:43 GMT Content-Length:222058 Content-Type:application/pdf Content-MD5: Last-Modified:Thu, 29 Sep 2022 19:07:39 GMT Content-Disposition:
In functions where blobs are handled there will be A LOT of request/response logs like these. I tend to wrap my operations with try-catch and log possible errors, so these are completely pointless to write.
I had the same problem when I used QueueTrigger, and my fix is to remove my TelemetryClient from singleton and in dependency injection. It also manages to remove all built-in logs. Example of the code.
public class Function1
{
private readonly TelemetryClient _telemetryClient;
public Function1()
{
_telemetryClient = TelemetryClientHelper.GetInstance();
}
}
public static class TelemetryClientHelper
{
private static TelemetryClient _telemetryClient;
public static TelemetryClient GetInstance()
{
if(_telemetryClient == null)
{
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.ConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
_telemetryClient = new TelemetryClient(telemetryConfiguration);
}
return _telemetryClient;
}
}
I am experiencing a problem when working with CAST web receiver. DRM Video does not start on the TV (Android TV). Preloader works endlessly. How to solve this problem?
The title and description in the player is shown.
The logs show errors:
"shakaErrorCode":6007
LICENSE_REQUEST_FAILED - 6007 - The license request failed. This could be a timeout, a network failure, or a rejection by the server. error.data[0] is a shaka.util.Error from the networking engine. (https://shaka-player-demo.appspot.com/docs/api/shaka.util.Error.html)
"detailedErrorCode":905
LOAD_FAILED - 905 - A load command failed. - Verify the load request is set up properly and the media is able to play. (https://developers.google.com/cast/docs/web_receiver/error_codes?hl=en)
Error 6007 indicates problems with the license server. We checked the request parameters on another player and the DRM video starts. This does not work in cast receiver.
The problem occurs on the physical device
Sender: Redmi Note 8 Pro
Device with chromecast: Android Box
Chromecast built-in: 1.56.276477
CAST SDK CAF Version: 3.0.0103
API Request
Request URL: https://widevine-license.vudrm.tech/proxy
Request Method: POST
Status Code: 200 OK
Remote Address: XXX
Referrer Policy: strict-origin-when-cross-origin
Response Headers
access-control-allow-headers: Content-Type,X-Vudrm-Token
access-control-allow-methods: GET,POST,OPTIONS
access-control-allow-origin: *
Connection: keep-alive
Content-Length: 716
content-type: application/octet-stream
date: Mon, 13 Jun 2022 07:59:00 GMT
server: istio-envoy
x-b3-parentspanid: 3d92950cdf3d42ca
x-b3-sampled: 0
x-b3-spanid: 46ff3c9c3e815372
x-b3-traceid: XXX
x-envoy-upstream-healthchecked-cluster: widevine-license.default
x-envoy-upstream-service-time: 18
x-forwarded-for: XXX,XXX
x-request-id: XXX
x-vudrm: app=widevine-proxy; version=2.4.1
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US
CAST-DEVICE-CAPABILITIES: {"bluetooth_supported":false,"display_supported":true,"hi_res_audio_supported":false,"remote_control_input_supported":false,"touch_input_supported":false}
Connection: keep-alive
Content-Length: 297
content-type: application/json
Host: widevine-license.vudrm.tech
Origin: XXX
Referer: XXX
sec-ch-ua
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Linux; Android 9.0; Build/PI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000
Request Payload
{"token":"XXX","drm_info":[8,4],"contentId":"VS-ADULTSWIM"}
receiver.js
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const playbackConfig = new cast.framework.PlaybackConfig();
const ContentType = {
DASH: 'application/dash+xml',
HLS: 'application/x-mpegurl'
};
const mediaFormatID = {
DASH: 2,
HLS: 4
};
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
};
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
LOG_TAG: cast.framework.LoggerLevel.DEBUG,
};
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, _reject) => {
// Configure player to parse DASH content
if (request.media.metadata.mediaFormatID == mediaFormatID.DASH) {
request.media.contentUrl = request.media.contentUrl;
request.media.contentType = ContentType.DASH;
// Customize the license url for playback
if (request.media.metadata.licenseUrl) {
playbackConfig.licenseUrl = request.media.metadata.licenseUrl;
playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
let token = request.media.metadata.token;
let contentId = request.media.metadata.contentId;
playbackConfig.licenseRequestHandler = requestInfo => {
requestInfo.withCredentials = false;
let body = {
token: token,
drm_info: Array.apply(null, new Uint8Array(requestInfo.content)),
contentId: contentId
};
body = JSON.stringify(body);
requestInfo.content = body;
requestInfo.headers["Content-Type"] = "application/json";
};
}
mpegDashStreamUrl = request.media.contentUrl;
vudrmToken = request.media.metadata.licenseUrl;
} else {
request.media.contentType = ContentType.HLS;
request.media.contentUrl = request.media.contentUrl;
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
}
// Add metadata
let metadata = new cast.framework.messages.GenericMediaMetadata();
metadata.title = request.media.metadata.title;
metadata.subtitle = request.media.metadata.subtitle;
request.media.metadata = metadata;
resolve(request);
});
});
context.start({playbackConfig: playbackConfig});
There are 3 handlers that are used by the Shaka response filters -
PlaybackConfig#manifestHandler
PlaybackConfig#licenseHandler
PlaybackConfig#segmentHandler
I added this code and the error was solved:
playbackConfig.licenseHandler = data => {
return new Promise((resolve, _reject) => {
resolve(new Uint8Array(data));
});
};
All of a sudden, I keep getting HTTP 500 errors in my self-hosted ServiceStack WS.
I have several requests already in place and they are working fine, but this one just wont work. I have added my license like this:
private void StartServiceStackService()
{
Licensing.RegisterLicenseFromFileIfExists("servicestack-license.txt".MapHostAbsolutePath());
_serviceStackHost = new ServiceStackWsHost(this, _frontEndModuleParameters, _alfaWebServicesSettings);
_serviceStackHost.Init();
if (!Debugger.IsAttached)
{
_serviceStackHost.Start(new[] { "http://+:8080/" });
}
else
{
_serviceStackHost.Start(new[] { "http://+:8081/" });
}
}
And the failing service is:
[Route(Bookings.BASE_PATH + "search", Verbs = "GET")]
public class SearchAddress : IReturn<SearchAddressResponse>
{
public string SearchString { get; set; }
}
public class SearchAddressResponse : ResponseBase
{
public string Test { get; set; }
// public List<Address> Addresses { get; set; }
}
internal class SearchAddressHandler : ServiceHandlerBase
{
public SearchAddressResponse Get(SearchAddress searchAddress)
{
return new SearchAddressResponse()
{
Test = "ASDASDASD"
};
}
}
And I call it using Fiddler4 like this:
GET http://192.168.0.147:8081/alfaonline/bookings/search?SearchString=123 HTTP/1.1
User-Agent: Fiddler
Host: 192.168.0.147:8081
AuthToken: a18b613c-23b2-4f4e-8934-ad8d6cbc57bb
DeviceUUID: 1baaace
and get this reply:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/html
Vary: Accept
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: ServiceStack/5.20 Net45/Windows
Date: Wed, 26 Sep 2018 11:28:31 GMT
0
If I instead return "null", like this:
[MyAuthenticate]
internal class SearchAddressHandler : ServiceHandlerBase
{
public SearchAddressResponse Get(SearchAddress searchAddress)
{
return null;
}
}
Fiddler gives me HTTP 204 OK:
HTTP/1.1 204 OK
Content-Length: 0
Vary: Accept
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: ServiceStack/5.20 Net45/Windows
Date: Wed, 26 Sep 2018 11:26:29 GMT
I see no errors, exceptions in VS in debug mode and "catch all" in Exception settings. I can put a breakpoint in the handler, and it breaks there, so the correct handler is executed.
UPDATE I have always been using Fiddler, now running Fiddler4. When I try the service, described below, in for example swagger (plugin to ServiceStack), it runs as expected. If I run the service in Postman, it runs as expected. But if I run it in Fiddler, I get HTTP 500
UPDATE 2 I also just noticed that going to http://127.0.0.1:8081/requestlogs also yields HTTP 500 error. More specifically, when I access /requestlogs and add the UncaughtExceptionHandlers, I see this error:
System.MissingMethodException: Method not found: 'System.String
ServiceStack.StringUtils.HtmlEncodeLite(System.String)'. at
ServiceStack.Formats.HtmlFormat.d__10.MoveNext()
at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine&
stateMachine) at
ServiceStack.Formats.HtmlFormat.SerializeToStreamAsync(IRequest req,
Object response, Stream outputStream) at
ServiceStack.HttpResponseExtensionsInternal.d__7.MoveNext()
Your first approach should be to get information about the Error:
Include a ResponseStatus property in your Response DTO if not already,
Enable Config.DebugMode
Add Debug Logging
Register Exception Handlers.
Using Apache Http 4.5 MultipartEntityBuilder and can't seem to figure out why the StringBody(String, ContentType) constructor doesn't actually output the Content-Type in the request form body.
public HttpRequestBase build() throws UnsupportedEncodingException {
HttpPost httpPost = new HttpPost("https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setContentType(ContentType.MULTIPART_FORM_DATA);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setBoundary("AAA");
//add form body
builder.addPart(generateJsonFormBodyPart());
//add file body
builder.addPart(generateFileFormBodyPart()); //<--intentionally omitted
HttpEntity multipart = builder.build();
httpPost.setEntity(multipart);
return httpPost;
}
private FormBodyPart generateJsonFormBodyPart() throws UnsupportedEncodingException{
StringBody json = new StringBody(packageJson(), ContentType.APPLICATION_JSON); //<--THIS DOESN'T SEEM TO WORK
StringBuilder buffer = new StringBuilder();
buffer.append("form-data");
String contentDisposition = buffer.toString();
FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create("application/json", json);
partBuilder.setField(MIME.CONTENT_DISPOSITION, contentDisposition);
FormBodyPart fbp = partBuilder.build();
return fbp;
}
The file portion outputs ok but I get a "Bad Request" return from the peer which I assume is because it has very specific request parameters.
Required Request Output
Accept: application/json
Content-Type: multipart/form-data; boundary=AAA
--AAA
Content-Type: application/json
Content-Disposition: form-data
json removed
--AAA
Content-Type: application/pdf
Content-Disposition: file; filename="test1.pdf";documentid=1
document removed
Actual Apache Http 4.5 Output
X-Docusign-Act-As-User: xyz#company.com
Accept-Encoding: gzip,deflate
User-Agent: Apache-HttpClient/4.5 (Java/1.8.0_65)
Connect-Time: 0
Host: requestb.in
Connection: close
Content-Length: 3178
Authorization: bearer xxxxrandomoauthtokenxxxxx
Content-Type: multipart/form-data; boundary=AAA; charset=ISO-8859-1
Via: 1.1 vegur
X-Request-Id: 89cd1cf5-3615-41e8-84ba-cd076a03af67
Total-Route-Time: 0
--AAA
Content-Disposition: form-data //<--the problem. should be application/json no?
{"status":"created","emailBlurb":"Welcome to Confluence","emailSubject":"Welcome to Confluence","documents":{"name":"Welcome to Confluence.html","documentId":"1","order":"1"},"recipients":{}}
--AAA
Content-Disposition: file; filename="Welcome.html";documentid=1
Content-Type: text/html; charset=ISO-8859-1
h t m l string removed
Q: So why does the ContentType in the StringBody constructor get ignored? Is there a workaround or am I doing it wrong?
I'm convinced this is a bug in Apache Http Mime for the FormBodyPart.build() when processing a StringBody. Evidence from release notes of 4.5.2 indicating bug fixes for other "body" types not outputting "Content-Type" supports this. I will be logging a defect.
The Workaround:
private FormBodyPart generateJsonFormBodyPart() throws UnsupportedEncodingException{
StringBody json = new StringBody(getMyJsonStuff(), ContentType.APPLICATION_JSON); //<--THE GOGGLES, THEY DO NOTHING!!
StringBuilder buffer = new StringBuilder();
buffer.append("form-data");
buffer.append("\r\n");
buffer.append("Content-Type: application/json"); //<--tack this on to the
String kludgeForDispositionAndContentType = buffer.toString();
FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create("stuff", json);
partBuilder.setField(MIME.CONTENT_DISPOSITION, kludgeForDispositionAndContentType);
FormBodyPart fbp = partBuilder.build();
return fbp;
}
Works like a charm.
I'm trying to do custom OAuth2 authorization server that will support Resource Owner Password Credentials flow. The authorization server is an WebAPI application hosted in IIS7.5.
I have configured startup class where I register custom OAuthServerProvider (AtcAuthorizationServerProvider).
[assembly: OwinStartup(typeof(ATC.WebApi.AuthorizationServer.Startup))]
namespace ATC.WebApi.AuthorizationServer
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new AtcAuthorizationServerProvider(),
RefreshTokenProvider = new AtcRefreshTokenProvider(),
AuthenticationMode = AuthenticationMode.Passive
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions(){});
}
}
}
In my custom provider class, I override ValidateClientAuthentication() function where I accept both client credentials receiving ways (in Body and in Authorization header).
public class AtcAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId = string.Empty;
string clientSecret = string.Empty;
// get client credentials from header or from body
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
{
context.TryGetFormCredentials(out clientId, out clientSecret);
}
//rest of code
Everything works fine when I send client_id and client_secret in body.
POST /ATC.WebApi.AuthorizationServer/token HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
grant_type=password&password=123456&username=myUser&client_id=myClient&client_secret=123%40abc
I get access token successfully.
{
"access_token": "3Fk_Ps10i45uL0zeCzIpvEh2WHKE8iJVNtKJ2XGWcQWXsT9jllKf...",
"token_type": "bearer",
"expires_in": 1799,
"refresh_token": "4c1097d17dd14df5ac1c5842e089a88e",
"as:client_id": "myClient"
}
However, if I use DotNetOpenAuth.OAuth2.WebServerClient which passes client_id and client_secret in Authorization header I will recieve 401.1 - Unauthorized HTTP response. I have found out that the ValidateClientAuthentication() is not fired.
Request than looks like this:
POST /ATC.WebApi.AuthorizationServer/token HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic C16b34lUjEyM0BhYmM=
Cache-Control: no-cache
grant_type=password&password=123456&username=myUser
The question is how to persuade probably the OWIN middle-ware firing my custom Provider in this case?
Well, I finally found out where is the trouble. There was Basic authentication allowed in my IIS, so IIS got the request and tried to Authenticate User which failed and IIS returned 401 Unauthorized immediately. So my OWIN middleware even did not receive the request to processing.