end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

OpenAMのlogin rest apiでlogin ticketを入手し、認証ページのhtmlをhttp get

2020/9/1 追記

このentry は、OpenAM ver.12 に対してのものでしたが、 その後、OpenAM ver.14 に対して行ったところ、 「'sso/json/sso/sessions'」のrequestで 501 not implemented というerrorが発生。

どうやら、APIの仕様が変更になっていた為、tomcat + openamの前段にある nginxの設定で、以下のように 「proxy_set_header Accept-API-Version 'resource=1.1, protocol=1.0'」を 加えることで解消。

location /sso/json/sso/sessions {
    proxy_pass http://127.0.0.1:28080/sso/json/sso/sessions;
    proxy_set_header Host $server_name;
    proxy_set_header Accept-API-Version 'resource=1.1, protocol=1.0'; ←追加★
    allow all;
}

以下のperl scriptの通り、LWP::UserAgent for perl , HTTP::Cookies for perl で実現できます

他参考 https://backstage.forgerock.com/docs/openam/13/dev-guide/

#!/usr/local/bin/perl
use utf8;
use strict;
use warnings;
use HTTP::Cookies;
use HTTP::Request;
use JSON;
use LWP::UserAgent;
use Data::Dumper;

my $SSO_HOST =                  'https://sso.hogehoge.com';
my $SSO_AUTHEN_API_PATH =       'sso/json/sso/authenticate';
my $SSO_VALIDATE_API_PATH =     'sso/json/sso/sessions';
my $PRIVATE_HOST =              'https://priv.hogehoge.com';
my $HTTP_TIMEOUT = 10;
my $LOCAL_COOKIE_FILE = "./cookie.txt";
my $COOKIE_DOMAIN = ".hogehoge.com";

my $UID_PW = {id=>"ないしょ",pw=>"ないしょ"};

main();


sub main {
    ## USER AGENT準備
    my $ua = LWP::UserAgent->new;
    $ua->timeout($HTTP_TIMEOUT);
    my $cookie_jar = HTTP::Cookies->new(file => $LOCAL_COOKIE_FILE,
                                        autosave => 1,
                                        ignore_discard => 1);
    $ua->cookie_jar($cookie_jar);

    ## SSOへlogin (login ticket取得)
    my $ret_auth = login_sso($ua);
    unless( $ret_auth ){
        die "fail login";
    }

    ## login ticketのvalidate (login idの取得)
    my $uid = validate_login($ua, $ret_auth);


    ## 認証要pageの取得
    get_private_page($ua,$uid,$ret_auth);
}

sub get_private_page {
    my ($ua,$uid,$ret_auth) = @_;
    
    my $cookie_jar = HTTP::Cookies->new(file => $LOCAL_COOKIE_FILE,
                                        autosave => 1,
                                        ignore_discard => 1);
    $cookie_jar->set_cookie(undef,              #version
                            "HTTP_uid",         #key
                            $uid,               #val
                            "/",                #path
                            $COOKIE_DOMAIN); #domain
    $cookie_jar->set_cookie(undef,                      #version
                            "iPlanetDirectoryPro",      #key
                            $ret_auth->{tokenId},       #val
                            "/",                        #path
                            $COOKIE_DOMAIN);         #domain
    $ua->cookie_jar($cookie_jar);
    
    my $top_url = join('/',$PRIVATE_HOST);
    my $req = HTTP::Request->new(GET => $top_url);

    my $res = $ua->request($req);
    if (not $res->is_success) {
        die $res->status_line;
    }

    # 認証要ページのHTMLが表示されます
    print $res->decoded_content;
}



sub validate_login {
    my ($ua, $ret_auth) = @_;

    my $url_validate =
        join('/',$SSO_HOST,$SSO_VALIDATE_API_PATH,$ret_auth->{tokenId});
    $url_validate .= '?_action=validate';
    my $req = HTTP::Request->new(POST => $url_validate);
    $req->header('Content-Type' => "application/json");

    my $res = $ua->request($req);
    if (not $res->is_success) {
        die $res->status_line;
    }

    my $ret_validate_json = $res->decoded_content;
    my $ret_validate = JSON::from_json($ret_validate_json);
    return $ret_validate->{uid};
}


sub login_sso {
    my ($ua) = @_;

    my $url = join('/',$SSO_HOST,$SSO_AUTHEN_API_PATH);
    my $req = HTTP::Request->new(POST => $url);
    $req->header('X-OpenAM-Username' => $UID_PW->{id});
    $req->header('X-OpenAM-Password' => $UID_PW->{pw});
    $req->header('Content-Type' => "application/json");

    my $res = $ua->request($req);
    if (not $res->is_success) {
        die $res->status_line;
    }

    my $ret_auth_json = $res->decoded_content;
    my $ret_auth = JSON::from_json($ret_auth_json);
    return $ret_auth;
}