AWS-SNS-Verify

 view release on metacpan or  search on metacpan

lib/AWS/SNS/Verify.pm  view on Meta::CPAN

    my $self = shift;
    my ($url_string) = @_;
    $url_string ||= '';

    return $url_string unless $self->validate_signing_cert_url;

    my $url = URI::URL->new($url_string);
    unless ( $url->can('host') ) {
        ouch 'Bad SigningCertURL', "The SigningCertURL ($url_string) isn't a valid URL", $self;
    }
    my $host = $url->host;

    # Match all regional SNS endpoints, e.g.
    # sns.<region>.amazonaws.com        (AWS)
    # sns.us-gov-west-1.amazonaws.com   (AWS GovCloud)
    # sns.cn-north-1.amazonaws.com.cn   (AWS China)
    my $dot = qr/\./;
    my $region = qr/[a-zA-Z0-9-]+/;
    unless ($host =~ /^ sns $dot $region $dot amazonaws $dot com(\.cn)? $/x) {
        ouch 'Bad SigningCertURL', "The SigningCertURL ($url_string) isn't an Amazon endpoint", $self;
    }

    return $url_string;
}

sub TO_JSON {
    my $self = shift;
    return unbless($self);
}

=head1 NAME

AWS::SNS::Verify - Verifies authenticity of SNS messages.

=head1 VERSION

version 0.0105

=head1 SYNOPSIS

 my $body = request->body; # example fetch raw body from Dancer
 my $sns = AWS::SNS::Verify->new(body => $body);
 if ($sns->verify) {
     return $sns->message;
 }

=head1 DESCRIPTION

This module will parse a message from Amazon Simple Notification Service and validate its signature. This way you know the message came from AWS and not some third-party. More info here: L<http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.ve...

=head1 METHODS

=head2 new

Constructor.

=over

=item body

Required. JSON string posted by AWS SNS. Looks like:

 {
    "Type" : "Notification",
    "MessageId" : "a890c547-5d98-55e2-971d-8826fff56413",
    "TopicArn" : "arn:aws:sns:us-east-1:041977924901:foo",
    "Subject" : "test subject",
    "Message" : "test message",
    "Timestamp" : "2015-02-20T20:59:25.401Z",
    "SignatureVersion" : "1",
    "Signature" : "kzi3JBQz64uFAXG9ZuAwPI2gYW5tT7OF83oeHb8v0/XRPsy0keq2NHTCpQVRxCgPOJ/QUB2Yl/L29/W4hiHMo9+Ns0hrqyasgUfjq+XkVR1WDuYLtNaEA1vLnA0H9usSh3eVVlLhpYzoT4GUoGgstRVvFceW2QVF9EYUQyromlcbOVtVpKCEINAvGEEKJNGTXQQUkPUka3YMhHitgQg1WlFBmf+oweSYUEj8+Ro...
    "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
    "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:041977924901:foo:20b2d060-2a32-4506-9cb0-24b8b9e605e1",
    "MessageAttributes" : {
        "AWS.SNS.MOBILE.MPNS.Type" : {"Type":"String","Value":"token"},
        "AWS.SNS.MOBILE.WNS.Type" : {"Type":"String","Value":"wns/badge"},
        "AWS.SNS.MOBILE.MPNS.NotificationClass" : {"Type":"String","Value":"realtime"}
    }
 }

=item certificate_string

By default AWS::SNS::Verify will fetch the certificate string by issuing an HTTP GET request to C<SigningCertURL>. The SigningCertURL in the message must be a AWS SNS endpoint.

If you wish to use a cached version, then pass it in.

=item validate_signing_cert_url (default: true)

If you're using a fake SNS server in your local test environment, the SigningCertURL won't be an AWS endpoint. If so, set validate_signing_cert_url to 0.

Don't ever do this in any kind of Production environment.

=back

=head2 verify

Returns a 1 on success, or die with an L<Ouch> on a failure.

=head2 message

Returns a hash reference of the decoded L<body> that was passed in to the constructor.

=head2 certificate_string

If you want to cache the certificate in a local cache, then get it using this method.


=head2 decode_signature

You should never need to call this, it decodes the base64 signature.

=head2 fetch_certificate

You should never need to call this, it fetches the signing certificate.


=head2 generate_signature_string

You should never need to call this, it generates the signature string required to verify the request.

=head2 valid_cert_url



( run in 1.703 second using v1.01-cache-2.11-cpan-5a3173703d6 )