src/Controller/SsoController.php line 19

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Alancting\Microsoft\JWT\AzureAd\AzureAdConfiguration;
  4. use Alancting\Microsoft\JWT\AzureAd\AzureAdIdTokenJWT;
  5. use Firebase\JWT\JWT;
  6. use League\OAuth2\Client\Provider\GenericProvider;
  7. use PhpParser\Comment\Doc;
  8. use Pimcore\Controller\FrontendController;
  9. use Pimcore\Model\DataObject\Account;
  10. use Pimcore\Model\DataObject\Manager;
  11. use Pimcore\Model\Document;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. use Symfony\Component\String\ByteString;
  15. use Pimcore\Cache;
  16. class SsoController extends FrontendController
  17. {
  18.     /**
  19.      * 跳转逻辑
  20.      * wcmManage: /sso/webLogin?app=wcm&usr=luy56&path=https://oneportalstg.medtronic.com.cn/#/login
  21.      * @Route("/sso/webLogin")
  22.      * @return
  23.      */
  24.     public function webLoginAction(Request $request) {
  25.         $app$request->get('app');
  26.         $networkId$request->get('usr');
  27.         $code=uniqid('em',true);
  28.         $account Account::getByNetworkId($networkId1);
  29.         if(!$account) {
  30.             $data = [
  31.                 'error'=>'登录成功但用户不存在',
  32.                 'errorDetail'=>'用户邮箱不存在,请先添加用户至wcm后台'
  33.             ];
  34.             return $this->render('default/msg.html.twig'$data);
  35.         }
  36.         $data = [
  37.                 'userId'=>$account->getNetworkId(),
  38.                 'email'=>$account->getEmail(),
  39.                 'displayName'=>$account->getName(),
  40.         ];
  41.         Cache::save($data,$code,[],120);
  42.         $path="https://oneportalstg.medtronic.com.cn/#/login";
  43.         if($app="crdn_sales"){
  44.             $path="https://education-stag.medtronic-digital.com/crdn_sales/login";
  45.         }
  46.         return $this->redirect($path.'?code='.$code);
  47.     }
  48.     /**
  49.      * 微软sso登录
  50.      * ESign: /sso/login?app=esign
  51.      * wcmAR: /sso/login?app=arsp
  52.      * wcmManage: /sso/login?app=wcm
  53.      * @Route("/sso/login")
  54.      * @return
  55.      */
  56.     public function loginAction(Request $request) {
  57.         // Initialize the OAuth client
  58.         $oauthClient = new GenericProvider([
  59.             'clientId'                => OAUTH_APP_ID,
  60.             'clientSecret'            => OAUTH_APP_SECRET,
  61.             'redirectUri'             => OAUTH_REDIRECT_URI,
  62.             'urlAuthorize'            => OAUTH_AUTHORITY.OAUTH_AUTHORIZE_ENDPOINT,
  63.             'urlAccessToken'          => OAUTH_AUTHORITY.OAUTH_TOKEN_ENDPOINT,
  64.             'urlResourceOwnerDetails' => '',
  65.             'scopes'                  => OAUTH_SCOPES
  66.         ]);
  67.         $authUrl $oauthClient->getAuthorizationUrl();
  68. //        $session = $request->getSession();
  69. //        $session->set('app', $request->get('app'));
  70. //        $session->set('oauthState', $oauthClient->getState());
  71.         setcookie('app'$request->get('app'));
  72.         $app$request->get('app');
  73.         $state=$oauthClient->getState();
  74.         setcookie('oauthState'.'_'.$state$oauthClient->getState());
  75.         
  76.         //2024-11-11 path parameter add.
  77.         
  78.         $path$request->get('path');
  79.         if(isset($path)){
  80.             setcookie('oauthPath'.'_'.$state,$path);
  81.         }else{
  82.             setcookie('oauthPath'.'_'.$state,"demo");
  83.         }
  84.         setcookie($state,$request->get('app'));//新增state对应App,用于反向查找App,用于验证浏览器端存储的state是否正确。
  85. //        $data = [
  86. //            'redirectUrl' => $authUrl,
  87. //            'error' =>'<img src="/img/load.gif" loading="lazy" alt="" class="load-img">',
  88. //            'errorDetail' => '正在加载登录页面,请稍等...'
  89. //        ];
  90. //        return $this->render('default/msg.html.twig', $data);
  91.         return $this->redirect($authUrl); // 进入微软登录
  92.     }
  93.     /**
  94.      * 微软sso登录重定向
  95.      * @Route("/sso/callback")
  96.      * @return
  97.      */
  98.        public function callbackAction(Request $request)
  99.     {
  100.         $session $request->getSession();
  101.         $state=$request->get('state');
  102.         $app $_COOKIE[$state];//获取state对应App。
  103.         $path$_COOKIE['oauthPath'.'_'.$state];//2024-11-11
  104.         $oauthState $_COOKIE['oauthState'.'_'.$state];//获取App对应State;
  105.         setcookie($state,'',time()-60);//清理Cookie App
  106.         setcookie('oauthState'.'_'.$state,'',time()-60);//清理Cookie State
  107.         if(!$oauthState) {
  108.             $redirectUrl '/sso/login?app='.$app;
  109.             $data = [
  110.             'redirectUrl' => $redirectUrl,
  111.             'error' => '重定向!',
  112.             'errorDetail' => '正在重新登录应用!'
  113.             ];
  114.             return $this->render('default/msg.html.twig'$data);
  115.         } else {
  116.             $code $request->get('code');
  117.             $state $request->get('state');
  118.             if (empty($state)) {
  119.                 $data = [
  120.                     'error'=>'no state',
  121.                     'errorDetail'=>'there is no expected state in the session'
  122.                 ];
  123.                 return $this->render('default/msg.html.twig'$data);
  124.             }
  125.             if ($state != $oauthState) {
  126.                 $data = [
  127.                     'error'=>'Invalid auth state',
  128.                     'errorDetail'=>'The provided auth state did not match the expected value. '.$state.' , '.$oauthState
  129.                 ];
  130.                 //ApplicationLogger::getInstance()->info('SSO State'.$state.' '.$oauthState);
  131.                 return $this->render('default/msg.html.twig'$data);
  132.             }
  133.             $redirectUrl '/sso/redirectUrl?code='.$code;
  134.             $kname=md5($code);
  135.             
  136.             //2024-11-11 added path;
  137.             $kpath='path'.'_'.$kname;
  138.             setcookie($kpath,$path);
  139.             
  140.             setcookie($kname,$app);//新增Code对应App,用于反向查找App
  141.         }
  142.         
  143.         $data = [
  144.             'redirectUrl' => $redirectUrl,
  145.             'error' => '登录成功!',
  146.             'errorDetail' => '正在验证用户信息'
  147.         ];
  148.         return $this->render('default/msg.html.twig'$data);
  149.     }
  150.     /**
  151.      * 内部跳转一次,使session生效
  152.      * @Route("/sso/redirectUrl")
  153.      * @return
  154.      */
  155.     public function redirectUrlAction(Request $request) {
  156.         $session $request->getSession();
  157.         $authCode $request->get('code');
  158.         $kname=md5($authCode);
  159.         
  160.         //2024-11-11 added path
  161.         $kpath='path'.'_'.$kname;
  162.         $path =$_COOKIE[$kpath];
  163.         
  164.         $app $_COOKIE[$kname];//更新为code绑定App。
  165.         setcookie($kname,'',time()-60);
  166.         // Authorization code should be in the "code" query param
  167.         if (!empty($authCode)) {
  168.             $oauthParams = [
  169.                 'client_id'                => OAUTH_APP_ID,
  170.                 'client_secret'            => OAUTH_APP_SECRET,
  171.                 'redirect_uri'             => OAUTH_REDIRECT_URI,
  172.                 'urlAuthorize'            => OAUTH_AUTHORITY.OAUTH_AUTHORIZE_ENDPOINT,
  173.                 'urlAccessToken'          => OAUTH_AUTHORITY.OAUTH_TOKEN_ENDPOINT,
  174.                 'urlResourceOwnerDetails' => '',
  175.                 'scopes'                  => OAUTH_SCOPES
  176.             ];
  177.             // Initialize the OAuth client
  178.             //$oauthClient = new GenericProvider($oauthParams);
  179.             try {
  180.                 // Make the token request
  181.                 //$accessToken = $oauthClient->getAccessToken('authorization_code', [
  182.                 //    'code' => $authCode
  183.                 //]);
  184.                 $authData $this->reqData('post'OAUTH_AUTHORITY.OAUTH_TOKEN_ENDPOINTarray_merge($oauthParams, [
  185.                     'grant_type'=>'authorization_code',
  186.                     'code'=>$authCode
  187.                 ]));
  188.                 //var_dump($authData);
  189.                 $access_token $authData['access_token'];
  190.                 $id_token $authData['id_token'];
  191.                 // var_dump($authData);
  192.                 // echo "</br>";
  193.                 // var_dump($id_token);
  194.                 // die();
  195.                 $config_options = [
  196.                     'tenant' => OAUTH_TENANT_ID,
  197.                     'tenant_id' => OAUTH_TENANT_ID// 租户id
  198.                     'client_id' => OAUTH_APP_ID// appid
  199.                     'config_uri' => OAUTH_AUTHORITY.'/v2.0/.well-known/openid-configuration?appid='.OAUTH_APP_ID// appid
  200.                     'idTokenCheck' => true
  201.                 ];
  202.                 $config = new AzureAdConfiguration($config_options);
  203.                 $id_token_jwt = new AzureAdIdTokenJWT($config$id_token);
  204. //                print_r($id_token_jwt->getPayload());
  205. //                print_r($id_token_jwt->get('email'));
  206.                 if($id_token_jwt->isExpired()) {
  207.                     $data = [
  208.                         'error'=>'Access failed',
  209.                         'errorDetail'=>'id token 过期'
  210.                     ];
  211.                     return $this->render('default/msg.html.twig'$data);
  212.                 }
  213.                 // 解析邮箱
  214.                 $arr explode('.'$access_token);
  215.                 $jsonData JWT::urlsafeB64Decode($arr[1]);
  216.                 $userInfo json_decode($jsonDatatrue);
  217.                 $email $userInfo['upn'];//20250417 Modify to networkid to fix the IAM team's change
  218.                 $networkId substr($email0stripos($email'@'));
  219.                 $azureCode ByteString::fromRandom(32);
  220.                 
  221.                 if($app=='wcm') {
  222.                     $manager Manager::getByAccount($email1);
  223.                     if(!$manager) {
  224.                         $data = [
  225.                             'error'=>'无权访问',
  226.                             'errorDetail'=>'管理员邮箱不存在'
  227.                         ];
  228.                         return $this->render('default/sso.html.twig'$data);
  229.                     }
  230.                     $manager->setSsoCode($azureCode);
  231.                     $manager->setPublished(true);
  232.                     $manager->save();
  233.                     return $this->redirect(ADMIN_DOMAIN.'#/login?code='.$azureCode);
  234.                 }elseif($app=='oneportal'){
  235.                     $code=uniqid('em',true);
  236.                     Cache::save($jsonData,$code,[],120);
  237.                     return $this->redirect('https://oneportalstg.medtronic.com.cn/#/login?code='.$code.'&user='.$jsonData);
  238.                 }elseif($app=='university'){
  239.                     $code=uniqid('em',true);
  240.                     $data = [
  241.                         'userId'=>$networkId,
  242.                         'email'=>$userInfo['unique_name'],
  243.                         'displayName'=>$userInfo['name'],
  244.                     ];
  245.                     Cache::save($data,$code,[],120);
  246.                     return $this->redirect('https://university.medtronic.com.cn/mdtuniversity/login'.'?code='.$code);
  247.                 }elseif($app=='academy'){
  248.                     $code=uniqid('em',true);
  249.                     $data = [
  250.                         'userId'=>$networkId,
  251.                         'email'=>$userInfo['unique_name'],
  252.                         'displayName'=>$userInfo['name'],
  253.                     ];
  254.                     Cache::save($data,$code,[],120);
  255.                     return $this->redirect('https://ma-wstag.medtronic.com.cn/login'.'?code='.$code);
  256.                 }elseif($app=='shapde_apv_academy_admin'){//2024-11-11
  257.                     $code=uniqid('em',true);
  258.                     $data = [
  259.                         'userId'=>$networkId,
  260.                         'email'=>$userInfo['unique_name'],
  261.                         'displayName'=>$userInfo['name'],
  262.                     ];
  263.                     Cache::save($data,$code,[],120);
  264.                     return $this->redirect('https://me.workatall.com/apv-lm/admin?role=admin&'.'code='.$code);
  265.                 }elseif($app=='shapde_apv_ academy _sales'){
  266.                     $code=uniqid('em',true);
  267.                     $data = [
  268.                         'userId'=>$networkId,
  269.                         'email'=>$userInfo['unique_name'],
  270.                         'displayName'=>$userInfo['name'],
  271.                     ];
  272.                     Cache::save($data,$code,[],120);
  273.                     return $this->redirect('https://me.workatall.com/apv-lm/login?role=sales&'.'code='.$code);
  274.                 }elseif($app=='ent_da_sales'){
  275.                     $code=uniqid('em',true);
  276.                     $data = [
  277.                         'userId'=>$networkId,
  278.                         'email'=>$userInfo['unique_name'],
  279.                         'displayName'=>$userInfo['name'],
  280.                     ];
  281.                     Cache::save($data,$code,[],120);
  282.                     return $this->redirect('https://me.workatall.com/entda/login'.'?code='.$code);
  283.                 }elseif($app=='shape_pvh_da_sales'){
  284.                     $code=uniqid('em',true);
  285.                     $data = [
  286.                         'userId'=>$networkId,
  287.                         'email'=>$userInfo['unique_name'],
  288.                         'displayName'=>$userInfo['name'],
  289.                     ];
  290.                     Cache::save($data,$code,[],120);
  291.                     return $this->redirect('https://me.workatall.com/pvh/login'.'?code='.$code);
  292.                 }elseif($app=='shape_pvh_static_sales'){
  293.                     $code=uniqid('em',true);
  294.                     $data = [
  295.                         'userId'=>$networkId,
  296.                         'email'=>$userInfo['unique_name'],
  297.                         'displayName'=>$userInfo['name'],
  298.                     ];
  299.                     Cache::save($data,$code,[],120);
  300.                     return $this->redirect('https://me.workatall.com/pvh_static/login'.'?code='.$code);
  301.                 }elseif($app=='ns_csf_da_ sales'){//2024-11-11
  302.                     $code=uniqid('em',true);
  303.                     $data = [
  304.                         'userId'=>$networkId,
  305.                         'email'=>$userInfo['unique_name'],
  306.                         'displayName'=>$userInfo['name'],
  307.                     ];
  308.                     Cache::save($data,$code,[],120);
  309.                     return $this->redirect('https://me.workatall.com/csf/login'.'?code='.$code);
  310.                 }elseif($app=='rdn'){
  311.                     $code=uniqid('em',true);
  312.                     $data = [
  313.                         'app'=>$app,
  314.                         'userId'=>$networkId,
  315.                         'email'=>$userInfo['unique_name'],
  316.                         'displayName'=>$userInfo['name']
  317.                     ];
  318.                     Cache::save($data,$code,[],120);
  319.                     return $this->redirect(APP_DOMAIN.'#/login?code='.$code);
  320.             
  321.                 }else {
  322.                     $account Account::getByNetworkId($networkId1);
  323.                     if(!$account) {
  324.                         $data = [
  325.                             'error'=>'登录成功但用户不存在',
  326.                             'errorDetail'=>'用户邮箱不存在,请先添加用户至wcm后台'
  327.                         ];
  328.                         return $this->render('default/msg.html.twig'$data);
  329.                     }
  330.                     if($app=='arsp') {
  331.                         $account->setAzureCode($azureCode);
  332.                         $account->setPublished(true);
  333.                         $account->save();
  334.                         $data = [
  335.                             'email'=>$email,
  336.                             'code'=>$azureCode,
  337.                             'domain'=>APP_DOMAIN,
  338.                             'error'=>'登录成功!',
  339.                             'errorDetail'=>'即将跳转至APP'
  340.                         ];
  341.                         return $this->render('default/sso.html.twig'$data);
  342.                     } elseif($app=='esign') {
  343.                         if ($account->getisLogin() != 1) {
  344.                             return $this->render('esign/message.html.twig', ['message' => '无登录权限']);
  345.                         }
  346.                         $admin = [
  347.                             'id' => $account->getId(),
  348.                             'account' => $account->getEmail(),
  349.                             'isRemove' => $account->getIsRemove(),
  350.                             'isLogin' => $account->getIsLogin(),
  351.                             'userType' => 'eSign',
  352.                         ];
  353.                         $session->set('admin'$admin);
  354.                         return $this->redirect('/esign/inquire');
  355.                     }elseif($app=='ehs') {
  356.                         if ($account->getEHSisLogin() != 1) {
  357.                             return $this->render('esign/message.html.twig', ['message' => '无登录权限']);
  358.                         }
  359.                         $admin = [
  360.                             'id' => $account->getId(),
  361.                             'account' => $account->getEmail(),
  362.                             'isRemove' => $account->getEHSIsRemove(),
  363.                             'isLogin' => $account->getEHSIsLogin(),
  364.                             'userType' => 'ehs',
  365.                         ];
  366.                         $session->set('admin'$admin);
  367.                         return $this->redirect('/ehs/inquire');
  368.                     }elseif($app=='compliance') {
  369.                         if ($account->getcomplianceIsLogin() != 1) {
  370.                             return $this->render('esign/message.html.twig', ['message' => '无登录权限']);
  371.                         }
  372.                         $admin = [
  373.                             'id' => $account->getId(),
  374.                             'account' => $account->getEmail(),
  375.                             'isRemove' => $account->getcomplianceIsRemove(),
  376.                             'isLogin' => $account->getcomplianceIsLogin(),
  377.                             'userType' => 'compliance',
  378.                         ];
  379.                         $session->set('admin'$admin);
  380.                         return $this->redirect('/compliance/inquire');
  381.                     }elseif($app=='carelink') {
  382.                         if ($account->getcarelinkIsLogin() != 1) {
  383.                             return $this->render('carelink/message.html.twig', ['message' => '无Carelink From App登录权限']);
  384.                         }
  385.                         $account->setcarelinkToken($azureCode);
  386.                         $account->setPublished(true);
  387.                         $account->save();
  388.                         $admin = [
  389.                             'id' => $account->getId(),
  390.                             'account' => $account->getEmail(),
  391.                             'isLogin' => $account->getcarelinkIsLogin(),
  392.                             'userType' => 'carelink',
  393.                             'code'=>$azureCode,
  394.                         ];
  395.                         $session->set('admin'$admin);
  396.                         return $this->redirect('/carelink/inquire');
  397.                     }else{//2024-11-11 added
  398.                     
  399.                         $code=uniqid('em',true);
  400.                         $usr=explode('@',$userInfo['unique_name']);
  401.                         
  402.                         $data = [
  403.                             'app'=>$app,
  404.                             'userId'=>$networkId,
  405.                             'email'=>$userInfo['unique_name'],
  406.                             'displayName'=>$userInfo['name'],
  407.                         ];
  408.                         Cache::save($data,$code,[],120);
  409.                         return $this->redirect($path.'?code='.$code);
  410.                     }
  411.                     
  412.                     
  413.                 }
  414.             } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
  415.                 $data = [
  416.                     'error'=>'Error requesting access token',
  417.                     'errorDetail'=>json_encode($e->getResponseBody())
  418.                 ];
  419.                 return $this->render('default/sso.html.twig'$data);
  420.             }
  421.         }
  422.         $data = [
  423.             'error'=>$request->get('error'),
  424.             'errorDetail'=>$request->get('error_description')
  425.         ];
  426.         return $this->render('default/msg.html.twig'$data);
  427.     }
  428.     /**
  429.      * 退出
  430.      * @Route("/sso/logout")
  431.      * @return
  432.      */
  433.     public function logoutAction(Request $request) {
  434.         $params $request->query->all();
  435.         $data = [
  436.             'error'=>'Logout',
  437.             'errorDetail'=>'已退出'
  438.         ];
  439.         return $this->render('default/msg.html.twig'$data);
  440.     }
  441.     public function reqData($method$url$data=[], $headers=[]) {
  442.         $ch curl_init();
  443.         curl_setopt($chCURLOPT_HTTPHEADER$headers);
  444.         curl_setopt($chCURLOPT_RETURNTRANSFER1);
  445.         curl_setopt($chCURLOPT_SSL_VERIFYPEER0);
  446.         curl_setopt($chCURLOPT_SSL_VERIFYHOST0);
  447.         curl_setopt($chCURLOPT_PROXY,MDT_CURL_PROXY);
  448.         $data http_build_query($data);
  449.         if($method=='get') {
  450.             curl_setopt($chCURLOPT_POST0);
  451.             $url .= '?'.$data;
  452.         } else {
  453.             curl_setopt($chCURLOPT_POSTFIELDS$data);
  454.             curl_setopt($chCURLOPT_POST1);
  455.         }
  456.         curl_setopt($chCURLOPT_URL$url);
  457.         $output curl_exec($ch);
  458.         $curl_info curl_getinfo($ch);
  459.         //var_dump($curl_info);
  460.         //var_dump($output);
  461.         curl_close($ch);
  462.         return json_decode($outputtrue);
  463.     }
  464.     /**
  465.      * 根据code获取sso user
  466.      * @Route("/sso/getUserByCode")
  467.      * @return
  468.      */
  469.     public function getUserByCodeAction(Request $request) {
  470.         header("Cache-Control: no-cached");
  471.         header("Access-Control-Allow-Credentials:true");
  472.         header("Content-Type: */*");
  473.         header("Access-Control-Allow-Headers: *");
  474.         header("Access-Control-Allow-Origin: *");
  475.         $code $request->query->get('code');
  476.         $user Cache::load($code);//2分钟销毁
  477.         return $this->json($user);
  478.     }
  479. }