How to catch the play.api.libs.openid.Errors$AUTH_CANCEL$ exception? - exception

Using Play Framework 2.1 with OpenID, if I cancel my authentication from the OpenID Provider, I get this exception :
[RuntimeException: play.api.libs.openid.Errors$AUTH_CANCEL$]
Here's my code :
Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
UserInfo userInfo = userInfoPromise.get(); // Exception thrown here
But since it's a Runtime exception, I can't catch it with a try/catch so I'm stuck on how to avoid exception and returns something nicer than a server error to the client.
How can I do that?

A Promise is success biased, for all its operations, it assumes it actually contains a value and not an error.
You get the exception because you try to call get on a promise which contains an untransformed error.
What you want is to determine if the Promise is a success or an error, you can do that with pattern matching for instance.
try this code:
AsyncResult(
OpenID.verifiedId.extend1( _ match {
case Redeemed(info) => Ok(info.attributes.get("email").getOrElse("no email in valid response"))
case Thrown(throwable) => {
Logger.error("openid callback error",throwable)
Unauthorized
}
}
)
)
You may want to read more on future and promises, I recommend this excellent article :
http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html
edit :
checking the documentation (http://www.playframework.com/documentation/2.1.0/JavaOpenID) in java it seems you are supposed to catch and handle exceptions yourself.
In any case, you should catch exceptions and if one is thrown redirect
back the user to the login page with relevant information.
something like this should work :
public class Application extends Controller {
public static Result index() {
return ok("welcome");
}
public static Result auth() {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("email", "http://schema.openid.net/contact/email");
final Promise<String> stringPromise = OpenID.redirectURL("https://www.google.com/accounts/o8/id", "http://localhost:9000/auth/callback",attributes);
return redirect(stringPromise.get());
}
public static Result callback() {
try{
Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
final UserInfo userInfo = userInfoPromise.get();
System.out.println("id:"+userInfo.id);
System.out.println("email:"+userInfo.attributes.get("email"));
return ok(userInfo.attributes.toString());
} catch (Throwable e) {
System.out.println(e.getMessage());
e.printStackTrace();
return unauthorized();
}
}
}

Related

Spring AMQP RPC consumer and throw exception

I have a consumer (RabbitListner) in RPC mode and I would like to know if it is possible to throw exception that can be treated by the publisher.
To make more clear my explication the case is as follow :
The publisher send a message in RPC mode
The consumer receive the message, check the validity of the message and if the message can not be take in count, because of missing parameters, then I would like to throw Exception. The exception can be a specific business exception or a particular AmqpException but I want that the publisher can handle this exception if it is not go in timeout.
I try with the AmqpRejectAndDontRequeueException, but my publisher do not receive the exception, but just a response which is empty.
Is it possible to be done or may be it is not a good practice to implement like that ?
EDIT 1 :
After the #GaryRussel response here is the resolution of my question:
For the RabbitListner I create an error handler :
#Configuration
public class RabbitErrorHandler implements RabbitListenerErrorHandler {
#Override public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) {
throw e;
}
}
Define the bean into a configuration file :
#Configuration
public class RabbitConfig extends RabbitConfiguration {
#Bean
public RabbitTemplate getRabbitTemplate() {
Message.addWhiteListPatterns(RabbitConstants.CLASSES_TO_SEND_OVER_RABBITMQ);
return new RabbitTemplate(this.connectionFactory());
}
/**
* Define the RabbitErrorHandle
* #return Initialize RabbitErrorHandle bean
*/
#Bean
public RabbitErrorHandler rabbitErrorHandler() {
return new RabbitErrorHandler();
}
}
Create the #RabbitListner with parameters where rabbitErrorHandler is the bean that I defined previously :
#Override
#RabbitListener(queues = "${rabbit.queue}"
, errorHandler = "rabbitErrorHandler"
, returnExceptions = "true")
public ReturnObject receiveMessage(Message message) {
For the RabbitTemplate I set this attribute :
rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
When the messsage threated by the consumer, but it sent an error, I obtain a RemoteInvocationResult which contains the original exception into e.getCause().getCause().
See the returnExceptions property on #RabbitListener (since 2.0). Docs here.
The returnExceptions attribute, when true will cause exceptions to be returned to the sender. The exception is wrapped in a RemoteInvocationResult object.
On the sender side, there is an available RemoteInvocationAwareMessageConverterAdapter which, if configured into the RabbitTemplate, will re-throw the server-side exception, wrapped in an AmqpRemoteException. The stack trace of the server exception will be synthesized by merging the server and client stack traces.
Important
This mechanism will generally only work with the default SimpleMessageConverter, which uses Java serialization; exceptions are generally not "Jackson-friendly" so can’t be serialized to JSON. If you are using JSON, consider using an errorHandler to return some other Jackson-friendly Error object when an exception is thrown.
What worked for me was :
On "serving" side :
Service
#RabbitListener(id = "test1", containerFactory ="BEAN CONTAINER FACTORY",
queues = "TEST QUEUE", returnExceptions = "true")
DataList getData() {
// this exception will be transformed by rabbit error handler to a RemoteInvocationResult
throw new IllegalStateException("mon expecion");
//return dataHelper.loadAllData();
}
On "requesting" side :
Service
public void fetchData() throws AmqpRemoteException {
var response = (DataList) amqpTemplate.convertSendAndReceive("TEST EXCHANGE", "ROUTING NAME", new Object());
Optional.ofNullable(response)
.ifPresentOrElse(this::setDataContent, this::handleNoData);
}
Config
#Bean
AmqpTemplate amqpTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
var rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter);
return rabbitTemplate;
}
#Bean
MessageConverter jsonMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.registerModule(new JavaTimeModule());
var jsonConverter = new Jackson2JsonMessageConverter(objectMapper);
DefaultClassMapper classMapper = new DefaultClassMapper();
Map<String, Class<?>> idClassMapping = Map.of(
DataList.class.getName(), DataList.class,
RemoteInvocationResult.class.getName(), RemoteInvocationResult.class
);
classMapper.setIdClassMapping(idClassMapping);
jsonConverter.setClassMapper(classMapper);
// json converter with returned exception awareness
// this will transform RemoteInvocationResult into a AmqpRemoteException
return new RemoteInvocationAwareMessageConverterAdapter(jsonConverter);
}
You have to return a message as an error, which the consuming application can choose to treat as an exception. However, I don't think normal exception handling flows apply with messaging. Your publishing application (the consumer of the RPC service) needs to know what can go wrong and be programmed to deal with those possibilities.

Return an existing razor view from middleware in asp.net core

In my custom exception middleware, I want to get exceptions processed and return the same resource with a user friendly message.
E.g When Account/Add throws an SqlException, I return Account/Add response with a message which stored in TempData from exception middleware. I already
got these view engine things done.
I found this extension method and usage for this purpose, with this, you can return all IActionResult implementations from middleware, great extension.
However, I could not find out how to return my conventional view that resides in my views folder such as Views/Account/Add
Exception Middleware
private readonly RequestDelegate _next;
public ExceptionHandler(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
HandleException(context, ex);
}
}
private void HandleException(HttpContext context, Exception exception)
{
//handle exception, log it and other stuff...
//....
var result = new ViewResult
{
ViewName = context.Request.Path.ToString(),
};
//WithDanger is an extension method writes message to tempdata
result.WithDanger("Error", exception.ToString());
//Extension method
context.WriteResultAsync(result);
}
This is what I tried but it is not working as I expected, it returns a blank page, it seems it does not make the razor view engine run to build my request page.
How can I make my middleware to return a ViewResult with my existing view properley?
There's a couple of things missing. In order to return a view using a relative path, you need to trim off the leading slash:
ViewName = context.Request.Path.ToString().TrimStart('/')
You're also not awaiting the WriteResultAsync call. Change it to something like
private TaskHandleException(HttpContext context, Exception exception)
{
//handle exception, log it and other stuff...
//....
var result = new ViewResult
{
ViewName = context.Request.Path.ToString().TrimStart('/'),
};
//WithDanger is an extension method writes message to tempdata
result.WithDanger("Error", exception.ToString());
//Extension method
return context.WriteResultAsync(result);
}
And make sure you await the call to HandleException:
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
await HandleException(context, ex);
}
}
That should work :)

How do I add errors to my Spring MVC REST Service?

How can I change/update the following REST call from Spring MVC to return a error if the user did not enter of the the two names I was coding for.. something like a not found?
#RequestMapping(value = "/{name}", method = RequestMethod.GET)
#ResponseBody
public User getName(#PathVariable String name, ModelMap model)
{
logger.debug("I am in the controller and got user name: " + name);
/*
Simulate a successful lookup for two users. This
is where your real lookup code would go.
*/
if ("name2".equals(name))
{
return new User("real name 2", name);
}
if ("name1".equals(name))
{
return new User("real name 1", name);
}
return null;
}
Define a new exception class, e.g. ResourceNotFoundException and throw an instance of this from your annotated controller method getName.
Then also define an annotated exception handler method in your Controller class to handle that exception, and return a 404 Not Found status code, potentially logging it.
#ExceptionHandler(ResourceNotFoundException.class)
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public void handleResourceNotFoundException(ResourceNotFoundException ex)
{
LOG.warn("user requested a resource which didn't exist", ex);
}
Or even returning some error message, using #ResponseBody annotation:
#ExceptionHandler(ResourceNotFoundException.class)
#ResponseStatus(value = HttpStatus.NOT_FOUND)
#ResponseBody
public String handleResourceNotFoundException(ResourceNotFoundException ex)
{
return ex.getMessage();
}
You could create an object specifically for returning error responses. That way, you can say whatever you want. For example:
#ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ResponseStatus> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex){
ResponseStatus responseStatus = new ResponseStatus("400", "Bad Request. " + ex);
responseStatus.setResponseStatusTime(timestampService.createTimestamp());
HttpStatus status = HttpStatus.BAD_REQUEST;
ResponseEntity<ResponseStatus> response = new ResponseEntity<ResponseStatus>(responseStatus, status);
return response;
}
In this example you can see that there is a ResponseStatus object. This object contains a field for a status code, status message, date and time. You may not need date and time but I find it useful for when someone sends me an error they have seen, because then it is easy to track down exactly where it happened in our server logs.

ServiceStack catch (WebServiceException ex) - has wrong ErrorCode

In my ServiceStack service, I throw an exception that has an inner exception. When I caught a WebServiceRequest on the client side, the ErrorCode was the inner exception type name.
This is bad for me because it doesn't allow me to respond to the specific exception type that was thrown on the server.
I'm failing to see why ServiceStack was designed this way. It's pretty typical to catch lower level exceptions and wrap them with more informative and sometimes end-user friendly exceptions.
How can I change the default behavior so it uses the surface level exception and not the inner-most?
After looking at the first example at https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling, I decided to check out at DtoUtils.HandleException, which looks like this:
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
if (ex.InnerException != null && !(ex is IHttpError))
ex = ex.InnerException;
var responseStatus = ex.ToResponseStatus();
if (EndpointHost.DebugMode)
{
// View stack trace in tests and on the client
responseStatus.StackTrace = GetRequestErrorBody(request) + ex;
}
Log.Error("ServiceBase<TRequest>::Service Exception", ex);
if (iocResolver != null)
LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
var errorResponse = CreateErrorResponse(request, ex, responseStatus);
return errorResponse;
}
The very first instruction replaces the exception with it's inner exception. I'm not sure what the the thinking was with that. It seems counter intuitive to me and so I just re-implemented the method in my AppHost class, removing that first if statement block:
public override void Configure(Container container)
{
ServiceExceptionHandler += (request, exception) => HandleException(this, request, exception);
}
/// <remarks>
/// Verbatim implementation of DtoUtils.HandleException, without the innerexception replacement.
/// </remarks>
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
var responseStatus = ex.ToResponseStatus();
if (EndpointHost.DebugMode)
{
// View stack trace in tests and on the client
responseStatus.StackTrace = DtoUtils.GetRequestErrorBody(request) + ex;
}
var log = LogManager.GetLogger(typeof(DtoUtils));
log.Error("ServiceBase<TRequest>::Service Exception", ex);
if (iocResolver != null)
DtoUtils.LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
var errorResponse = DtoUtils.CreateErrorResponse(request, ex, responseStatus);
return errorResponse;
}
This is obviously not ideal, since I had to copy a bunch of code that is totally unrelated to the problem that I had with the original implementation. It makes me feel like I have to maintain this method whenever I update ServiceStack. I would love to here of a better way to accomplish this.
Anyway, I have the exception handling that I like in my client code:
catch (WebServiceException ex)
{
if (ex.ErrorCode == typeof (SomeKindOfException).Name)
{
// do something useful here
}
else throw;
}
It doesn't seem like you'll have to maintain a bunch of code. You're writing one method to implement your own error handling. You could try calling DtoUtils.HandleException(this, request, exception) in your own method and modify the HttpError object returned. Not sure you have access to change all properties/values you're looking for.
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
HttpError err = (HttpError)DtoUtils.HandleException(this, request, ex);
err.Reponse = ex.InnerException;
}

What to Return? Error String, Bool with Error String Out, or Void with Exception

I spend most of my time in C# and am trying to figure out which is the best practice for handling an exception and cleanly return an error message from a called method back to the calling method.
For example, here is some ActiveDirectory authentication code. Please imagine this Method as part of a Class (and not just a standalone function.)
bool IsUserAuthenticated(string domain, string user, string pass, out errStr)
{
bool authentic = false;
try
{
// Instantiate Directory Entry object
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
// Force connection over network to authenticate
object nativeObject = entry.NativeObject;
// No exception thrown? We must be good, then.
authentic = true;
}
catch (Exception e) { errStr = e.Message().ToString(); }
return authentic;
}
The advantages of doing it this way are a clear YES or NO that you can embed right in your If-Then-Else statement. The downside is that it also requires the person using the method to supply a string to get the Error back (if any.)
I guess I could overload this method with the same parameters minus the "out errStr", but ignoring the error seems like a bad idea since there can be many reasons for such a failure...
Alternatively, I could write a method that returns an Error String (instead of using "out errStr") in which a returned empty string means that the user authenticated fine.
string AuthenticateUser(string domain, string user, string pass)
{
string errStr = "";
try
{
// Instantiate Directory Entry object
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
// Force connection over network to authenticate
object nativeObject = entry.NativeObject;
}
catch (Exception e) { errStr = e.Message().ToString(); }
return errStr;
}
But this seems like a "weak" way of doing things.
Or should I just make my method "void" and just not handle the exception so that it gets passed back to the calling function?
void AuthenticateUser(string domain, string user, string pass)
{
// Instantiate Directory Entry object
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
// Force connection over network to authenticate
object nativeObject = entry.NativeObject;
}
This seems the most sane to me (for some reason). Yet at the same time, the only real advantage of wrapping those 2 lines over just typing those 2 lines everywhere I need to authenticate is that I don't need to include the "LDAP://" string. The downside with this way of doing it is that the user has to put this method in a try-catch block.
Thoughts?
Is there another way of doing this that I'm not thinking of?
There is no "one size fits all". If you return a flag, that makes it easy to use a method in if() and loops. Exceptions always need a lot of boiler plate code. If you just want a string which you can display to the user (say, in a web UI), returning the error string (or null for "no error") is good, too.
But most of the time, I throw an exception (and in Java a subclass of RuntimeException) because that allows me to return more than a single information about the error (like: Which file caused the error? Which line/column? What was I doing? Which field in a form should be marked as illegal? etc).
In your case, you can't handle the exception in your method, so you shouldn't catch it. Only catch it when you can do something about it.
In this example, I agree, you should let the exception flow through to the consumer. However, as an alternative to the approaches you highlighted, consider this approach.
You can use a response object to hold information coming out of a method run, for example:
public abstract class BaseResponse
{
public bool IsOk { get; protected set;}
public string Message { get; protected set; }
}
public class AuthenticationResponse: BaseResponse
{
public AuthenticationResponse(bool isOk): this(isOk, "") {}
public AuthenticationResponse(bool isOk, string message)
{
IsOk = isOk;
Message = message;
}
}
AuthenticationResponse IsUserAuthenticated(string domain, string user, string pass)
{
bool authentic = false;
string errStr;
try
{
// Instantiate Directory Entry object
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass);
// Force connection over network to authenticate
object nativeObject = entry.NativeObject;
// No exception thrown? We must be good, then.
authentic = true;
}
catch (Exception e) { errStr = e.Message().ToString(); }
return new AuthenticationResponse(authentic, errStr);
}
Then to use it in your if statements:
AuthenticationResponse response;
if((response = IsUserAuthenticated("domain", "user", "pass")).IsOk)
{
// do successful activity
} else {
Console.WriteLine(response.Message)
}
The trick is the return value of an assignment operation is the value that was assigned. So, we can do the assignment and the valid check in the same line. If you didn't need to hold onto the result of the call, you could simply call the method and check the IsOk property.
if(IsUserAuthenticated("domain", "user", "pass").IsOk)
{
// do successful activity
}
Then you can build up your custom response object to return any combination of values from your method as you need.
Don't handle the exception or return a message of any kind. Let the consumer of your method take care of this.