Mozilla-Persona

 view release on metacpan or  search on metacpan

lib/Mozilla/Persona/Server.pm  view on Meta::CPAN

{   my ($self, $args) = @_;
    $self->{MP_pem_fn}   = $args->{private_pem} or panic;
    $self->{MP_cookie}   = $args->{cookie_name} or panic;
    $self->{MP_domain}   = $args->{domain}      or panic;
    $self->{MP_aliparms} = $args->{aliases}
       || { class => 'Mozilla::Persona::Aliases' };
    $self->{MP_valparms} = $args->{validator}
       || { class  => 'Mozilla::Persona::Validate::Table'
          , pwfile => '/etc/persona/passwords'
          };
    $self;
}


sub fromConfig($)
{   my ($class, $fn) = (shift, shift);
    my $config = decode_json read_file $fn;
    $class->new(%$config, @_);
}

#-----------------

sub cookie()  {shift->{MP_cookie}}
sub domain()  {shift->{MP_domain}}


sub aliases()
{   my $self = shift;
    return $self->{MP_aliases}
        if $self->{MP_aliases};

    my $config = $self->{MP_aliparms} || {};

    # load alias expansion plugin
    my $class = delete $config->{class} or panic;
    eval "require $class"; panic $@ if $@;

    $self->{MP_aliases} = $class->new(%$config);
}


sub validator()
{   my $self = shift;
    return $self->{MP_validator}
        if $self->{MP_validator};

    my $config = $self->{MP_valparms} || {};

    # load username/password validator
    my $class = delete $config->{class} or panic;
    eval "require $class"; panic $@ if $@;

    $self->{MP_validator} = $class->new(%$config);
}


sub privatePEM()
{   my $self = shift;

    my $pem  = read_file $self->{MP_pem_fn};
    my $key  = Crypt::OpenSSL::RSA->new_private_key($pem);
    $key->use_pkcs1_padding;
    $key->use_sha256_hash;
    $key;
}

#------------------------

sub getSession($)
{   my ($self, $cgi) = @_;
    my $cookie  = $cgi->cookie($self->cookie)
        or error __x"no session cookie";

    my $session = CGI::Session->new('driver:File', $cookie)
        or error __x"invalid session cookie";

    $session;
}


sub _sign($$$)
{   my ($self, $client_pubkey, $email, $duration) = @_;

   # NB.  Treating the jwcrypto code as the spec here.
    my $issued_at = int(1000*time);

    my %cert      =
      ( iss          => $self->domain
      , exp          => $issued_at + 1000*$duration
      , iat          => $issued_at
      , "public-key" => $client_pubkey
      , principal    => { email => $email }
      );

    my %header     =
      ( typ          => 'JWT'
      , alg          => 'RS256'
      );

    my $header_enc = encode_base64url encode_json \%header;
    my $cert_enc   = encode_base64url encode_json \%cert;

    my $key       = $self->privatePEM or return;
    my $sig_enc    = encode_base64url $key->sign("$header_enc.$cert_enc");

    "$header_enc.$cert_enc.$sig_enc";
}

sub actionSign($)
{   my ($self, $cgi) = @_;

    my $session  = $self->getSession($cgi);
    my $user     = $session->param('user');

    print $cgi->header(-content_type => MIME_JSON);

    my $user_pubkey  = $cgi->param('pubkey')
        or error __x"nothing to sign for {user}", user => $user;

    my $duration = $cgi->param('duration') || 24*3600;



( run in 0.881 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )