• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NIT-Administrative-Systems / SysDev-laravel-soa / 7805057844

06 Feb 2024 07:28PM UTC coverage: 45.675% (-0.2%) from 45.913%
7805057844

push

github

web-flow
Housekeeping (#162)

11 of 35 new or added lines in 14 files covered. (31.43%)

9 existing lines in 7 files now uncovered.

264 of 578 relevant lines covered (45.67%)

14.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.05
/src/Auth/WebSSOAuthentication.php
1
<?php
2

3
namespace Northwestern\SysDev\SOA\Auth;
4

5
use GuzzleHttp\Exception\ClientException;
6
use Illuminate\Auth\AuthenticationException;
7
use Illuminate\Contracts\Auth\Authenticatable;
8
use Illuminate\Foundation\Auth\RedirectsUsers;
9
use Illuminate\Http\Request;
10
use Illuminate\Support\Facades\Auth;
11
use Illuminate\Support\Str;
12
use Laravel\Socialite\Facades\Socialite;
13
use Laravel\Socialite\Two\InvalidStateException;
14
use Northwestern\SysDev\SOA\Auth\Entity\ActiveDirectoryUser;
15
use Northwestern\SysDev\SOA\Auth\Entity\OAuthUser;
16
use Northwestern\SysDev\SOA\Auth\Strategy\NoSsoSession;
17
use Northwestern\SysDev\SOA\Auth\Strategy\WebSSOStrategy;
18

19
trait WebSSOAuthentication
20
{
21
    use RedirectsUsers, WebSSORoutes;
22

23
    /**
24
     * OpenAM WebSSO login action.
25
     */
26
    public function login(Request $request, WebSSOStrategy $sso_strategy)
27
    {
28
        try {
29
            $netid = strtolower($sso_strategy->login($request, $this->login_route_name));
18✔
30
        } catch (NoSsoSession $e) {
15✔
31
            return redirect($e->getRedirectUrl());
9✔
32
        }
33

34
        $user = app()->call(\Closure::fromCallable('static::findUserByNetId'), ['netid' => $netid]);
3✔
35
        throw_if($user === null, new AuthenticationException());
3✔
36

37
        Auth::login($user);
3✔
38

39
        return $this->authenticated($request, $user) ?: redirect()->intended($this->redirectPath());
3✔
40
    }
41

42
    /**
43
     * OpenAM WebSSO logout action.
44
     */
45
    public function logout(WebSSOStrategy $sso_strategy)
46
    {
47
        Auth::logout();
×
48

UNCOV
49
        return $sso_strategy->logout($this->logout_return_to_route);
×
50
    }
51

52
    public function oauthLogout($postLogoutRedirectUri = null)
53
    {
54
        Auth::logout();
6✔
55

56
        if ($postLogoutRedirectUri != null) {
6✔
57
            $url = $this->oauthDriver()->getLogoutUrl().'?post_logout_redirect_uri='.urlencode($postLogoutRedirectUri);
3✔
58

59
            return redirect($url);
3✔
60
        }
61

62
        return redirect($this->oauthDriver()->getLogoutUrl());
3✔
63
    }
64

65
    /**
66
     * Azure AD OAuth initiator action
67
     */
68
    public function oauthRedirect()
69
    {
70
        return $this->oauthDriver()->redirect();
3✔
71
    }
72

73
    /**
74
     * OAuth callback URL, where users are sent when they're
75
     */
76
    public function oauthCallback(Request $request)
77
    {
78
        try {
79
            $userInfo = $this->oauthDriver()->user();
12✔
80
        } catch (InvalidStateException $e) {
9✔
81
            // Should be resolvable by starting the flow over
82
            return redirect(route($this->oauth_redirect_route_name));
3✔
83
        } catch (ClientException $e) {
6✔
84
            /**
85
             * Handle specific failures that we know can be resolved by re-starting the auth flow.
86
             * Anything more general from Guzzle should rethrow and be handled
87
             * by the app's exception handler.
88
             */
89
            if (
90
                $e->getCode() === 400
3✔
91
                && Str::contains($e->getMessage(), 'OAuth2 Authorization code was already redeemed')
3✔
92
            ) {
93
                return redirect(route($this->oauth_redirect_route_name));
3✔
94
            }
95

96
            throw $e;
×
97
        }
98

99
        $oauthUser = new ActiveDirectoryUser($userInfo->token, $userInfo->getRaw());
3✔
100

101
        $user = app()->call(
3✔
102
            \Closure::fromCallable('static::findUserByOAuthUser'),
3✔
103
            ['oauthUser' => $oauthUser]
3✔
104
        );
3✔
105
        throw_if($user === null, new AuthenticationException());
3✔
106

107
        Auth::login($user);
3✔
108

109
        return $this->authenticated($request, $user) ?: redirect()->intended($this->redirectPath());
3✔
110
    }
111

112
    /**
113
     * Retrieve a user model for a given OAuth profile.
114
     *
115
     * By default, this method will pass the netID through to ::findUserByNetId instead
116
     * of doing anything on its own. This is for backwards-compatibility -- if you've used
117
     * OpenAM SSO in the past (or plan to in the future), the two methods can be used interchangably.
118
     *
119
     * In cases where you wish to utilize data from the Azure AD profile (like email, name, phone, etc),
120
     * you can implement this method and return a Laravel user directly, without invoking the
121
     * ::findUserByNetID method.
122
     */
123
    protected function findUserByOAuthUser(OAuthUser $oauthUser): ?Authenticatable
124
    {
125
        return app()->call(
×
126
            \Closure::fromCallable('static::findUserByNetID'),
×
127
            ['netid' => $oauthUser->getNetid()]
×
128
        );
×
129
    }
130

131
    /**
132
     * Retrieve a user model for a given netID.
133
     *
134
     * This is an opportunity to create a user in your DB, if needed.
135
     *
136
     * If you do not have a user store, a plain-old PHP object implementing
137
     * the Illuminate\Contracts\Auth\Authenticatable interface is sufficient.
138
     */
139
    protected function findUserByNetID(string $netid): ?Authenticatable
140
    {
141
        throw new \Exception('findUserByNetID is not implemented, but must be implemented.');
×
142
    }
143

144
    /**
145
     * Post-authentication hook.
146
     *
147
     * You may return a response here, e.g. a redirect() somewhere,
148
     * and it will be respected.
149
     */
150
    protected function authenticated(Request $request, $user)
151
    {
152
        //
153
    }
6✔
154

155
    /**
156
     * @return \Laravel\Socialite\Contracts\Provider
157
     */
158
    protected function oauthDriver()
159
    {
160
        $driver = Socialite::driver('northwestern-azure')->scopes($this->oauthScopes());
×
161

162
        if (! config('services.azure.redirect')) {
×
163
            $driver = $driver->redirectUrl(route($this->oauth_callback_route_name, [], true));
×
164
        }
165

166
        return $driver;
×
167
    }
168

169
    /**
170
     * Additional scopes for the user.
171
     *
172
     * @return array
173
     */
174
    protected function oauthScopes()
175
    {
176
        return ['https://graph.microsoft.com/User.Read'];
×
177
    }
178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc